Compare commits

...

200 Commits

Author SHA1 Message Date
45f2312979 remove depricated features 2021-09-09 15:14:19 +03:00
a602142dcb disable doc target 2021-09-02 11:48:08 +03:00
5b49c00168
Merge pull request #1 from KDE/master
refresh
2021-09-02 09:56:29 +03:00
Albert Astals Cid
e9fd31b4a1 Fix wrong condition protecting test execution 2021-08-06 17:15:30 +02:00
Christophe Giboudeaux
7ead054437 Don't create pkgconfig files for Qt 6 builds
Qt 6 doesn't provide pkgconfig files.
2021-06-05 08:35:27 +02:00
Albert Astals Cid
b2e54520a3 Increase version 2021-05-31 23:12:57 +02:00
Tobias Junghans
5cc26f77f0 CI: add job for Qt 6 build/test 2021-05-29 22:28:27 +00:00
Tobias Junghans
2c3992f075 Add Qt 6 build support
The Core5Compat module is still required for QTextCodec and some
difficult remaining QRegExp -> QRegularExpression migrations.
2021-05-29 22:28:27 +00:00
Tobias Junghans
0c3db8a062 Start Qt 6 port
Still a few occurrences of QRegExp and QTextCodec need to be replaced
in order to drop the dependency on the Core5Compat module. Besides this
QCA builds fine with Qt 6.1 and passes all tests.
2021-05-29 22:28:27 +00:00
Tobias Junghans
974f8ec8d0 Migrate from QScopedPointer to std::unique_ptr
QScopedPointer::take() is deprecated since Qt 6.1 so we can switch
to std::unique_ptr everywhere to be consistent.
2021-05-29 22:28:27 +00:00
Tobias Junghans
040d7d6348 Use QVariant::fromValue() for custom types 2021-05-29 22:28:27 +00:00
Tobias Junghans
d8f1e6cb9c Remove QChar::Null from latin1 strings
QString::fromLatin1(QByteArray) includes the null characters from the
byte array which makes BigInteger and Certificate tests fail since
QCOMPARE distinguishes between QString("123") and QString("123\u0000").
2021-05-29 22:28:27 +00:00
Tobias Junghans
9443ba76ba Migrate from qrand() to std::rand()
qrand() is deprecated since Qt 5.15.
2021-05-29 22:28:27 +00:00
Tobias Junghans
effbe387a0 Use QDateTime::to/fromSecsSinceEpoch()
QDateTime::to/fromTime_t() are deprecated since Qt 5.8.
2021-05-29 22:28:27 +00:00
Tobias Junghans
e6a15466ae Make retval of size()/count() match format string
Starting with Qt 6 qsizetype is returned (equals size_t).
2021-05-29 22:28:27 +00:00
Tobias Junghans
35366fea78 Use QStringView for Qt >= 5.15.2
QStringView::mid() behaves identically to QString::mid() starting with
Qt 5.15.2.
2021-05-29 22:28:27 +00:00
Tobias Junghans
3e90e13d5e Use Qt::endl 2021-05-29 22:28:27 +00:00
Tobias Junghans
91ff0aa0db Use new QAbstractSocket::errorOccurred() signal
It's in Qt 5.15 already.
2021-05-29 22:28:27 +00:00
Tobias Junghans
564e906dd1 Use QString::split(..., Qt::SplitBehavior, ...)
It's in Qt 5.14 already.
2021-05-29 22:28:27 +00:00
Tobias Junghans
d3d16fcc17 CI: switch to Ubuntu 20.10 to have Qt >= 5.14
KDE Frameworks requires Qt 5.14 already so we should adopt that. This
will also save quite a few #ifdefs when migrating to Qt 6.
2021-05-29 22:28:27 +00:00
Mark Nalimov
797b430540 Minor docs fix 2021-05-24 11:01:43 +03:00
Albert Astals Cid
ecdd0538dd Fix CMSut::signverify_message_invalid failing "randomly"
Once in a blue moon it happens that signedResult1[signedResult1.size() -
2] is a 0, so setting it to 0 doesn't break the signature validation, so
   check if it's a 0 and if it is, set it to 1
2021-02-05 16:45:07 +00:00
Albert Astals Cid
aa26b43be2 CI: give the plugin path for tests, otherwise some are not found
also run the tests on the debian:unstable CI to have testing with
different versions of dependencies
2021-02-05 16:47:13 +01:00
Albert Astals Cid
bc94cc08e1 openssl 1.1.1i made verification of empty messages always succeed
BUGS: 432519
2021-02-05 16:40:19 +01:00
Albert Astals Cid
2d7e7e8242 increase version 2021-02-02 23:51:45 +01:00
Albert Astals Cid
32275f1a74 Move moc include outside the QCA namespace
It's the right thing to do and also fixes build with gcc 11
2021-01-24 20:07:09 +00:00
Albert Astals Cid
1bcde93efc CI: Switch to new clang-format 2021-01-24 17:54:53 +00:00
Albert Astals Cid
e9e0f2085d Update the Qt requirement to what we actually test on CI 2020-12-10 19:51:38 +01:00
Albert Astals Cid
bd31ef1587 gitlab-ci: use eatmydata in apt-get
apt-get uses several fsync() calls on each package it installs, and that's
very slow, especially on non-SSD. eatmydata turns fsync into no-op, which
makes package installation much faster (it can cause corruption if there's
power loss or similar, but that doesn't matter in CI where we throw away
the whole container anyway).
2020-12-09 22:32:13 +00:00
Albert Astals Cid
7174e6ed70 Disable performance-no-automatic-move
It's too noisy with Qt classes
2020-12-09 21:33:05 +01:00
Albert Astals Cid
0684db8255 Add .git-blame-ignore-revs and some instructions for clang-format 2020-09-07 02:29:40 +02:00
Albert Astals Cid
dfb96ac596 Check clang-format at CI stage 2020-09-07 02:29:36 +02:00
Albert Astals Cid
f62a8ee8f7 Run clang-format
find . \( -name "*.cpp" -or -name "*.h"  -or -name "*.c"  -or -name "*.cc" \) -exec clang-format -i {} \;

If you reached this file doing a git blame, please see README.clang-format (added 2 commits in the future of this one)
2020-09-07 02:13:47 +02:00
Sergey Ilinykh
04dbe5ca7d Add clang-format file 2020-09-07 02:13:09 +02:00
Albert Astals Cid
db8ff052a9 Add a clang-format off marker
Otherwise clang-format unoptimizes the code
2020-09-07 02:13:09 +02:00
Albert Astals Cid
f88abb0697 Rewrite code a bit so clang-format doesn't break exceptions
clazy and clang-tidy comments needs to in the proper place
2020-09-07 02:11:39 +02:00
Sergey Ilinykh
0fd3c4cb26 Fixed windows.h auto ordering 2020-09-06 23:46:15 +02:00
Albert Astals Cid
0d174fea58 More values().contains() -> contains() 2020-09-06 23:41:53 +02:00
Albert Astals Cid
fb926ae7b2 Rewrite the values().contains() with a single contains() 2020-09-06 21:31:10 +02:00
Albert Astals Cid
6f4e01f92d qca-gcrypt: mark functions only used in one file as static 2020-07-13 18:59:28 +02:00
Alexander Volkov
71a1f95cba qca-gcrypt: Add support for HKDF 2020-07-13 16:55:56 +00:00
Larry Shaffer
f899a6aaad
Add macOS framework major version
- Use of major is like Qt, Qwt, etc.

Signed-off-by: Yurii Kolesnykov <root@yurikoles.com>
2020-07-06 14:25:24 +03:00
Albert Astals Cid
6c5486c227 Increase version 2020-07-04 10:51:52 +02:00
Albert Astals Cid
dd323fb8dc Update rootcerts.pem 2020-07-04 10:51:30 +02:00
Albert Astals Cid
6ee845ba60 ossl: Fix memory leak when querying for tls supported cipher suites 2020-06-22 22:55:29 +02:00
Albert Astals Cid
5d027c8012 tlsunittest: Fix memory leak 2020-06-22 22:53:55 +02:00
Albert Astals Cid
e23bf00919 pipeunittest: Fix memory leak 2020-06-22 22:52:44 +02:00
Albert Astals Cid
cfc80a9d6e ossl: Fix memory leak in CRL handling
ASN1_INTEGER_to_BN returns memory that needs to be freed
2020-06-22 22:46:13 +02:00
Albert Astals Cid
a014df24c5 ossl: Fix memory leak in fromPKCS12 2020-06-22 22:03:39 +02:00
Albert Astals Cid
c68a5e449f Fix memory leak in keybundle unittest 2020-06-22 22:03:39 +02:00
Albert Astals Cid
3242caee6a ossl: pkcs12: Don't crash on unknown private key type
BUGS: 423355
2020-06-22 22:03:35 +02:00
Friedrich W. H. Kossebau
ae5dec259f API dox: update some links in main page 2020-05-29 16:28:48 +02:00
Friedrich W. H. Kossebau
3b35392d13 API dox: fix generation of example tlssocket.cpp 2020-05-29 16:28:08 +02:00
Friedrich W. H. Kossebau
27dcf14de4 Add support for API docs generation with kapidox 2020-05-29 16:27:19 +02:00
Ivan Romanov
cabc7d32da Fix OpenSSL cipher names
OpenSSL provides own function to get cipher suite name by id.
No any sense to support own cipher suites list. Also now
this plugin will provide not just all available cipher suites.
But only these which enabled and can be used.

For old SSLv3 protocol ciphers have TLS variant names. It changes
prefix SSL with TLS.
2020-05-20 20:41:00 +05:00
Ivan Romanov
26af53173e Set minimum OpenSSL version in CMake 2020-05-20 19:07:01 +05:00
Ivan Romanov
b69aab2431 Fix KDE Licensing Policy problem
Added csv from https://www.iana.org/assignments/tls-parameters/tls-parameters-4.csv.
Also applied GPL license to gen-tls-parameters.sh and tls-parameters.cpp.
2020-05-19 20:08:41 +05:00
Ivan Romanov
cf929ce541 Add sh script to generate tls cipher strings 2020-05-18 14:45:48 +05:00
Ivan Romanov
bb9c771f4f Update TLS ClientCertificateType Identifiers 2020-05-18 00:18:21 +05:00
Albert Astals Cid
886d37792c Wrap char * in QStringLiteral
Compile++ for mac
2020-04-05 16:05:12 +00:00
Harald Sitter
77d127249c make memset easier to read
instead of manually calculating the size, just use sizeof on the members.
they are arrays, so the compiler can do the work for us.

Reviewers: sitter, vonreth

Reviewed By: sitter

Differential Revision: https://phabricator.kde.org/D9447

Diff By: Aleksey Nikolaev
2020-03-19 14:36:39 +01:00
Albert Astals Cid
cfea73392b Fix cross-compile under fedora mingw 2020-03-10 17:41:56 +01:00
Albert Astals Cid
02585a58e3 add a few const 2020-02-28 13:45:30 +01:00
Albert Astals Cid
4cf5d1965f Add more const qualifiers 2020-02-24 16:24:46 +01:00
Albert Astals Cid
06ad9c62b5 Increase version 2020-02-24 15:31:51 +01:00
Albert Astals Cid
30a9249dd9 Mark a few byte arrays as const 2020-02-17 17:39:40 +01:00
Albert Astals Cid
c1a028c345 Add const to a few lists 2020-02-16 12:11:57 +01:00
Albert Astals Cid
4100770e32 clang: Also enable the compile warnings
and turn some casts to reinterpret cast to make it clear "we know what
we're doing"
2020-02-15 12:29:54 +01:00
Albert Astals Cid
f944220634 Modernize cmake a bit: Remove confusing else and endif text 2020-02-15 12:29:54 +01:00
Albert Astals Cid
ad1b9e1b07 Enable QT_NO_CAST_FROM_ASCII 2020-02-15 10:21:12 +00:00
Albert Astals Cid
197b49677d openssl: Access NID_crl_number more correctly 2020-02-15 10:48:43 +01:00
Albert Astals Cid
9582a7970e openssl: Access NID_crl_reason more correctly 2020-02-15 10:47:03 +01:00
Albert Astals Cid
957e8ab4be test: Remove unused variable 2020-02-15 09:15:35 +00:00
Albert Astals Cid
8b171279e9 clazy: enable qstring allocation warning 2020-02-13 01:07:24 +01:00
Albert Astals Cid
4a98dbdcd9 Increase version for beta release 2020-02-12 18:53:56 +01:00
Albert Astals Cid
e2029649b9 clang-tidy: enable modernize-deprecated-headers and modernize-use-nullptr 2020-02-12 17:14:33 +01:00
Albert Astals Cid
c0ac498159 clazy: Enable container-anti-pattern
Except in the tests where being slow and convenient is better than fast
2020-02-12 16:55:18 +01:00
Albert Astals Cid
a29518b978 Add operator= to BigInt
Also make it just be implemented with the default as the tests
show that is enough

Fixes warning in newer gcc
2020-02-11 16:31:11 +01:00
Albert Astals Cid
001f827a4f Drop support for openssl <= 1.1 2020-02-11 14:09:19 +01:00
Albert Astals Cid
24e702e6cd Update rootcerts.pem 2020-02-10 00:36:27 +01:00
Albert Astals Cid
d26d7a7959 Add more override
And fix okular -> qca copy&paste typo ^_^
2020-02-09 01:21:32 +01:00
Albert Astals Cid
5ddf120260 More modern NSS/cmake 2020-01-30 18:23:59 +01:00
Albert Astals Cid
93336bb110 Enable more clang-tidy modernize checks 2020-01-30 18:02:17 +01:00
Albert Astals Cid
8ee19a09e2 Add a few modernize clang-tidy checks 2020-01-30 17:37:15 +01:00
Albert Astals Cid
0398e228de Add clang-tidy to the clazy CI 2020-01-30 16:55:33 +01:00
Albert Astals Cid
a177dbaae4 Remove QPROC_SIGNAL_RELAY define
It was always defined anyway, so makes the code easier to understand
2020-01-30 16:29:56 +01:00
Albert Astals Cid
4c31e0c81f static -> static const 2020-01-30 13:52:21 +01:00
Albert Astals Cid
c5f5a4c038 clazy: Enable level2 except a few checks
also a few of the manual checks
2020-01-29 17:36:23 +01:00
Albert Astals Cid
5e2751fe85 clazy: enable level1 2020-01-29 16:53:08 +01:00
Albert Astals Cid
294cf98f59 Enable all clazy level 0 tests except one
one: containter-anti-pattern, needs some bigger rework
2020-01-29 15:16:08 +01:00
Albert Astals Cid
dce16514fe Enable a clazy CI
Starting with only missing-qobject-macro check enabled
2020-01-29 14:31:55 +01:00
Albert Astals Cid
7df8f7e215 Move to the new connect syntax
QProcess::errorOccurred is since 5.6 so increase min version
2020-01-29 08:34:13 +00:00
Albert Astals Cid
9e9366bbef Add .gitlab-ci 2020-01-27 16:07:05 +01:00
Albert Astals Cid
c685525849 Fix compilation with older Qt 2020-01-27 15:21:03 +01:00
Albert Astals Cid
32c6eb989c Link only to invent as repo 2020-01-25 00:56:36 +01:00
Albert Astals Cid
e8a7e1f12b affinix.com is dead 2020-01-25 00:56:03 +01:00
Albert Astals Cid
987e447551 We don't work with Qt4 anymore 2020-01-25 00:55:47 +01:00
Albert Astals Cid
d61a1ce875 Rearrange README a bit 2020-01-25 00:54:38 +01:00
Albert Astals Cid
f9fc3f356f remove unused variables 2020-01-24 10:46:27 +01:00
Albert Astals Cid
d298a11af7 SASL_AUTH_EXTERNAL wants a char * not a char **
Reviewers: sitter

Reviewed By: sitter

Differential Revision: https://phabricator.kde.org/D26879
2020-01-23 23:33:03 +01:00
Albert Astals Cid
d3fd2d9a10 Don't store the char * of a bytearray.toLatin1().data()
It's dangling memory
2020-01-23 17:45:05 +01:00
Albert Astals Cid
d3f8ea684e QString::mid -> midRef 2020-01-23 17:40:59 +01:00
Albert Astals Cid
3d6e4e7c2e Enable QT_NO_URL_CAST_FROM_STRING 2020-01-23 17:29:27 +01:00
Albert Astals Cid
6a1d268315 Enable QT_NO_CAST_FROM_BYTEARRAY 2020-01-23 17:26:29 +01:00
Albert Astals Cid
2a988a2021 Add QT_NO_CAST_TO_ASCII 2020-01-23 17:19:49 +01:00
Albert Astals Cid
6b229c3ae2 Add QT_STRICT_ITERATORS 2020-01-23 17:18:46 +01:00
Albert Astals Cid
79af2e7fdf Enable QT_USE_QSTRINGBUILDER and QT_NO_NARROWING_CONVERSIONS_IN_CONNECT 2020-01-22 19:31:37 +01:00
Albert Astals Cid
dbef5838d4 Enable QT_NO_SIGNALS_SLOTS_KEYWORDS 2020-01-22 19:31:28 +01:00
Albert Astals Cid
80f58d05f0 Fix BotanHKDFContext::clone
And excercise it in the unittest
2020-01-21 17:41:24 +01:00
Albert Astals Cid
4449dd088b Fix KDFContex clone in botan/gcrypt
And excercise that from the unittest
2020-01-21 01:19:50 +01:00
Albert Astals Cid
29c7d98898 Fix MACContext clone in botan/gcrypt/nss
And excercise that from the unittest
2020-01-21 01:12:07 +01:00
Albert Astals Cid
0ce2b3927e Fix HashContext in botan/gcrypt/nss
And make sure the hashunittest exercises them
2020-01-21 00:54:10 +01:00
Albert Astals Cid
501a539c22 botan: Require botan2
It's already 2 years old, more than sensible to ask for uptodate crypto
stuff
2020-01-20 23:32:04 +01:00
Albert Astals Cid
156dd01575 hashunittest: Make finding the files easier 2020-01-20 23:16:15 +01:00
Albert Astals Cid
24df5ea742 hashunittest: Fail not warn if test files can't be found 2020-01-20 23:12:30 +01:00
Albert Astals Cid
c0d8f1807d botan: remove stdout here
This gets called on initialization and most people won't even probably
will be asking for this particular method so no need to be annoying
2020-01-20 23:04:36 +01:00
Albert Astals Cid
bdb0e9d37d hashunittest: test all providers 2020-01-20 23:03:31 +01:00
Albert Astals Cid
c1a4ad1ab1 botan: check md2 is supported before saying it is 2020-01-20 23:03:28 +01:00
Albert Astals Cid
61daaffee6 openssl: Reenable whirpool
If that means ancient openssl don't work, that's the problem of people
using ancient openssl
2020-01-20 22:49:09 +01:00
Albert Astals Cid
416d89268e ciphertest: Test all providers 2020-01-20 20:02:02 +01:00
Albert Astals Cid
391360f145 gcrypt: disable des, seems it fails on some cases 2020-01-20 20:02:02 +01:00
Albert Astals Cid
f429960d58 qcrypt: Fix crash on platforms where uint and size_t are different 2020-01-20 20:02:02 +01:00
Albert Astals Cid
a77ea02b8d botan: Check if ciphers are supported before saying they are
Now all tests pass :)
2020-01-20 20:02:02 +01:00
Laurent Montel
acb45eeb84 Use nullptr 2020-01-20 13:37:51 +01:00
Albert Astals Cid
694abbcafa kdfunittest: Test all the backends
and be less verbose when a backend doesn't support what we're testing,
it's fine if the some other one does
2020-01-20 01:01:02 +01:00
Albert Astals Cid
5105fc4981 botan: Make sure it supports pbkdf1(md2) before saying we to
At least my version (2.13.0) doesn't seem to support it

"Fixes" kdfunittest
2020-01-20 00:46:41 +01:00
Albert Astals Cid
b9d80939c6 botan: Fix crash if asking for something botan doesn't provide
Fixes crash in KDFUnitTest with my botan installation
2020-01-19 22:32:32 +01:00
Albert Astals Cid
1b061d63a8 gpg: use the loopback pinentry
otherwise we don't get asked back for passphrase like we want to
2020-01-19 22:17:53 +01:00
Albert Astals Cid
8adde8d9c7 Add file i forgot to commit, sorry ^_^ 2020-01-19 22:16:08 +01:00
Albert Astals Cid
a0194d7ffd qFind -> std::find 2020-01-19 18:01:15 +01:00
Albert Astals Cid
ba3fb44b49 qVariantSetValue -> QVariant::setValue 2020-01-19 17:59:03 +01:00
Albert Astals Cid
70406170f5 Cleanup Qt version checks 2020-01-19 17:57:35 +01:00
Albert Astals Cid
4ad7e911d9 QString::sprintf -> QString::asprintf 2020-01-19 17:45:25 +01:00
Albert Astals Cid
0816a04f42 qSort -> std::sort 2020-01-19 17:35:06 +01:00
Albert Astals Cid
83c23c7a3a QTime -> QElapsedTimer 2020-01-19 17:32:15 +01:00
Albert Astals Cid
d71f4c279b Drop Qt4 support 2020-01-19 17:19:23 +01:00
Albert Astals Cid
3293100c42 remove slot that was declared but never implemented 2020-01-19 17:01:19 +01:00
Albert Astals Cid
00d311d90f Add override 2020-01-19 16:28:44 +01:00
Albert Astals Cid
326399794e qca-botan: Don't crash if BotanCipherContext fails
Makes the cipher unit test at least not crash (even if it doesn't pass)
2020-01-19 16:27:09 +01:00
Albert Astals Cid
691395e193 BigInteger: Test the toArray/fromArray 2020-01-19 12:16:37 +01:00
Nicolas Fella
c167627675 Don't use obsolete qVariantFromValue
Test Plan: Same tests as before pass

Reviewers: iromanov, sitter, dfaure, #frameworks

Reviewed By: sitter

Differential Revision: https://phabricator.kde.org/D25802
2019-12-07 23:27:42 +01:00
Harald Sitter
4b11437f7a change the android condition to a getuid check
it's unclear if anyone would ever run a qca app as root on android, but
in case they do we'd still want to drop

discussed in D23289
2019-09-07 17:26:31 +02:00
Peter Petrik
2895ca34dd Fix QCA android build
Summary:
to be able to run Input App (Android), we have to avoid calls to setuid. Otherwise the application coredumps on this call during runtime.

see https://github.com/lutraconsulting/input-sdk/blob/master/android/recipes/qca/recipe.sh

Reviewers: sitter, dfaure

Reviewed By: sitter

Differential Revision: https://phabricator.kde.org/D23289
2019-09-07 17:26:28 +02:00
R.J.V. Bertin
0be2a2ced3 Call cmake_minimum_required() before project()
Also correct a typo.

Differential revision: https://phabricator.kde.org/D8510
2019-06-08 17:20:00 +02:00
R.J.V. Bertin
b614cdbd6e also set the INSTALL_NAME_DIR for regular Mac libs
Failing to do so can cause linker/loader failures when installing
the QCA library to a non-standard location (e.g. the Qt install tree).
2019-06-08 16:18:03 +02:00
Harald Sitter
db5f82be2a bump version to 2.2.1 2019-04-23 14:04:15 +02:00
Harald Sitter
b38e904a4e Partially revert "Require CMake 3.4 and use the OpenSSL imported libs"
Summary:
This reverts the QcaMacro changes of
commit 1137ed5f07d137296874f7dd1ee629f903507161 as they seem fairly
unrelated to the actual openssl change and proof to cause persistent issues
with buildability.

Further revert "unbreak build by moving away from deprecated exec_program"
This reverts commit 32419c899c77b8f5ece374d2453ee37e89af7c10.
Which was done in an attempt to remidy the build problems.

Further revert "Actually abort after the message that tells people to set CMAKE_INSTALL_PREFIX"
This reverts commit 63fd27fbce780bccb9c9b3ff6649888cfd809c6a.
Which was also done in an attempt to fix the problems.

BUG: 406353

Test Plan:
- when configuring without any arguments the qmake derived paths are used and correct
- when configuring with CMAKE_INSTALL_PREFIX the paths are accordingly reported below that

QCA prefix is /opt
Plugins will be installed to /opt/lib/qca-qt5
Binary will be installed to /opt/bin
Library will be installed to /opt/lib
Public headers will be installed to /opt/include/Qca-qt5
Private headers will be installed to /opt/include/Qca-qt5
Feature file will be installed to /opt/mkspecs/features
Documentation will be installed to /opt/share/doc/qca-qt5/html
Man page will be installed to /opt/share/man
Pkg-config file will be installed to /opt/lib/pkgconfig

Reviewers: dfaure, arojas, vonreth

Reviewed By: dfaure, arojas

Differential Revision: https://phabricator.kde.org/D20408
2019-04-23 14:03:50 +02:00
Harald Sitter
32419c899c unbreak build by moving away from deprecated exec_program
Summary:
since 1137ed5f07d137296874f7dd1ee629f903507161 which bumped cmake and
started using TARGET_FILE for the qmake calls qca failed to build for me.
I fail to understand why exactly that is but I suspect it has to do with
the fact that exec_program is deprecated and may not be working
(correctly?) with generator expressions.

moving to the not deprecated execute_process fixes clean builds on my
system and is at the very least a move away from deprecated tech with
no downsides

Test Plan: rm -rf * && cmake -DCMAKE_INSTALL_PREFIX=/usr ..

Reviewers: asturmlechner, dfaure, vonreth

Reviewed By: dfaure

Differential Revision: https://phabricator.kde.org/D20228
2019-04-08 11:32:48 +02:00
David Faure
63fd27fbce Actually abort after the message that tells people to set CMAKE_INSTALL_PREFIX
Test Plan:
`mkdir build ; cd build ; cmake ..` no longer prints out weird stuff after
the "!!!!" error message, it actually stops there as intended (AFAICS).
2019-03-29 09:17:38 +01:00
David Faure
7b03a01b18 Fix compilation error due to QByteArray/QString mixup
main.cpp:4251:35: error: no matching function for call to ‘QByteArray::indexOf(QString&)’
2019-03-17 00:09:21 +01:00
Hannah von Reth
1137ed5f07 Require CMake 3.4 and use the OpenSSL imported libs
Summary:
Fixes
 00:09:45.140 [162/278] Linking CXX shared module lib/qca-qt5/crypto/libqca-ossl.dylib
00:09:45.140 FAILED: lib/qca-qt5/crypto/libqca-ossl.dylib
00:09:45.140 : && /usr/bin/clang++ -O2 -g -DNDEBUG -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.12.sdk -bundle -Wl,-headerpad_max_install_names  -o lib/qca-qt5/crypto/libqca-ossl.dylib plugins/qca-ossl/CMakeFiles/qca-ossl.dir/qca-ossl.cpp.o  lib/qca-qt5.framework/Versions/2.2.0/qca-qt5 /Users/packaging/Craft/BinaryCache/macos-64-clang/lib/libssl.dylib /Users/packaging/Craft/BinaryCache/macos-64-clang/lib/libcrypto.dylib -lcrypto /Users/packaging/Craft/BinaryCache/macos-64-clang/lib/QtCore.framework/QtCore -framework CoreFoundation -framework Security && :
00:09:45.140 ld: library not found for -lcrypto
00:09:45.140 clang: error: linker command failed with exit code 1 (use -v to see invocation)

Reviewers: dfaure, bcooksley, volkov

Reviewed By: dfaure

Differential Revision: https://phabricator.kde.org/D17913
2019-03-04 12:16:36 +01:00
Alexander Volkov
32343842d3 Fix build with botan < 2 and openssl < 1.1
Summary:
This commit amends f57d661416ecbdfbf9c16d8116c296cfdcbeb7d6.
HKDF support was added only in the new versions of the libs.

Reviewers: dfaure, bcooksley

Reviewed By: dfaure

Differential Revision: https://phabricator.kde.org/D16248
2018-10-17 14:54:34 +03:00
Nicolás Alvarez
ad50594cb2 Fix repeated 'the the' in comments. 2018-10-15 10:26:08 -03:00
Alexander Volkov
f57d661416 Introduce HKDF
Summary:
It's needed for implementation of Secret Service:
https://specifications.freedesktop.org/secret-service/ch07s03.html

Reviewers: iromanov, sitter, #frameworks, dfaure

Reviewed By: dfaure

Subscribers: dfaure

Differential Revision: https://phabricator.kde.org/D15510
2018-10-15 14:30:05 +03:00
Alexander Volkov
98eead0058 Add .arcconfig 2018-09-14 19:20:10 +03:00
Harald Sitter
da4d1d06d4 Openssl fix deprecation warnings
Summary:
Openssl fix deprecation warnings

Removed unused function: X509_SIG_getm

deprecated warnings for:
ASN1_STRING_data
DSA_generate_parameters
RSA_generate_key
RAND_pseudo_bytes

Tested with openssl-1.0.2l on ubuntu:14.04
Deprecation warning spotted with openssl-1.1.0.g-1

one deprecation warning left: TLSv1_client_method

Reviewers: sitter, fvogt

Reviewed By: fvogt

Differential Revision: https://phabricator.kde.org/D11616
2018-06-19 11:46:09 +02:00
Andreas Sturmlechner
e854f357f4 Make Qt5Network conditional on BUILD_TESTS
Summary: I did not find it in use somewhere else.

Reviewers: iromanov, sitter, rjvbb

Reviewed By: rjvbb

Subscribers: fvogt

Differential Revision: https://phabricator.kde.org/D12129
2018-06-06 11:21:17 +02:00
Antonio Rojas
78503bf574 Recommit botan 2 support without making botan mandatory
Differential Revision: https://phabricator.kde.org/D11997
2018-04-12 10:03:12 +02:00
Ben Cooksley
01cbb31770 Revert "Add botan 2 support"
This change adds a mandatory dependency on Botan, which is not available at this time within Craft.
As this change was not notified to Sysadmin and because it has left us in a state whereby we are unable to get the Windows CI system back up and running, this is being reverted so it can be brought back online.

Please reintroduce this change once support for having Botan as optional is restored

This reverts commit 47163784d74232e3a844fc42897bffc7eff817b4.
2018-04-12 19:48:32 +12:00
Antonio Rojas
47163784d7 Add botan 2 support
Botan 1.10 will be EOL'd this year. This patch is a rough port to botan 2 API. Also:

- Removes support for botan < 1.10 to simplify code (1.10 was released 7 years ago)
- Ports the cmake module to use pkgconfig, since botan-config doesn't exist anymore in v2.
- To minimize ifdef'd code, botan2 unique_ptr's are release'd
- Removes -ansi C(XX)FLAGS, botan 2 requires C++11

Differential Revision: https://phabricator.kde.org/D11997
2018-04-11 21:43:57 +02:00
Harald Sitter
3e6a86b6b8 Merge branch 'v2.1' 2018-03-22 12:16:44 +01:00
Harald Sitter
b1abd13319 Qca: fix cypto.prf on MacOs
Summary: Fixed crypto.prf for frameworks build with qt5

Reviewers: iromanov, sitter, rjvbb

Reviewed By: sitter, rjvbb

Differential Revision: https://phabricator.kde.org/D11480
2018-03-22 12:15:57 +01:00
Harald Sitter
ee536fd995 Merge remote-tracking branch 'origin/v2.1' 2018-03-22 12:02:31 +01:00
Fabian Vogt
d58e20ee65 Add support for OpenSSL 1.1.0
Test Plan:
Ran the testsuite with OpenSSL 1.1.0g and 1.0.2j, all passed.
Using this code with kdeconnect and okteta successfully on my system now.

Reviewers: iromanov

Subscribers: anthonyfieroni, alonbl, heikobecker, cfeck, asturmlechner, bero, rdieter

Differential Revision: https://phabricator.kde.org/D9416
2018-01-04 20:02:38 +01:00
Ivan Romanov
159e144abf Disable missed openssl cipher suites
Fedora 26 has no them.
2017-09-30 15:45:59 +05:00
Ivan Romanov
8871dcd2e1 Fix CMake warning
CMP 0020 is deprecated. Avoid using of old behaviour.
2017-09-18 22:28:00 +05:00
Ivan Romanov
df794c0181 Remove deprecated keyword 2017-07-08 09:53:45 +05:00
Alon Bar-Lev
5f18ebc705 build: fix C++11 throwing distructors
For >=C++11, explicitly mark throwing destructors `noexcept(false)`

Thanks: Peter-Levine <plevine457@gmail.com>
2017-03-21 12:34:29 +02:00
Ivan Romanov
be55b9c98d Fix Qt5.7 warning 2017-03-01 13:22:48 +05:00
Ivan Romanov
aec63cd2e6 Bump version to 2.1.3 2017-02-06 17:29:44 +05:00
Ivan Romanov
89800d4341 tlsunittest: disable some ciphers 2017-02-06 17:29:01 +05:00
Ivan Romanov
f4b2eb0ced Fix previous commit 2017-01-29 15:20:17 +05:00
Ivan Romanov
b435c1b87b Avoid @rpath on Mac OS 2017-01-29 14:06:08 +05:00
Samuel Gaist
7ba0ee591e OS X build and warning fix
Revert "Add missed file"

This reverts commit 4c9f27270e0a7c00c10cbc56ce5c6842b47e5ab2.

FindCoreFoundation.cmake is not needed since CoreFoundation
is a system framework. Its use has been removed by
commit f223ce03d4b94ffbb093fc8be5adf8d968f54434

Acked by: Ivan Čukić

REVIEW: 126285
2016-10-20 13:34:23 +02:00
Ivan Romanov
d320ef4fdb Add some missed headers to Qt Creator project 2016-10-10 21:50:18 +05:00
Ivan Romanov
28245c731e Add base64 convenience functions 2016-09-19 10:48:11 +05:00
Ivan Romanov
19ec49f89a Bump version to 2.2.0 2016-09-19 10:48:11 +05:00
Ivan Romanov
57878ff44f Add support for AES GCM and AES CCM modes
Only qca-openssl now can use GCM and CCM. CCM is not tested and
planed for future.
2016-09-19 10:48:11 +05:00
Ivan Romanov
4efa158c31 Improve documentation 2016-09-19 10:47:25 +05:00
Ivan Romanov
fdf961cfa3 Require CMake 3.0 on Mac OS X 2016-08-26 08:53:37 +05:00
Raphael Kubo da Costa
84f53aea25 qca-ossl: Remove SHA0 from all_hash_types() when it is not available.
Commit 0dbed8e ("qca-ossl: Fix build without support for SHA-0") forgot
to add an #ifdef check for SHA0 support in all_hash_types().

REVIEW: 128700
2016-08-18 08:52:57 +02:00
Ivan Romanov
6a685d6b0b Refactor cipherunittest 2016-08-09 11:26:47 +05:00
Ivan Romanov
759ff45dba Fix indents in cipherunittest 2016-08-09 10:48:36 +05:00
Rolf Eike Beer
eb5eeca609 fix the mkspecs install directory when cross-compiling using Qt5
REVIEW:128308
2016-07-02 19:05:19 +02:00
Rolf Eike Beer
601fd3a051 fix base64 decoding on ARM
This code was broken on ARM and other architectures where "char" is unsigned by
default.

First, it breaks with newer compilers with errors like:

  .../src/qca_textfilter.cpp:314:2: error: narrowing conversion of '-1' from 'int' to 'char' inside { } [-Wnarrowing]

Second, if the compiler would just allow this conversion then the unsigned char
would hold 255, which would not be sign extended when cast to an int later, so
all the checks "< 0" will never trigger, and so invalid input characters cannot
be detected.

REVIEW:128295
BUG:364495
2016-06-27 18:24:02 +02:00
Ivan Romanov
a0c9a28728 Fix imported target name 2016-05-27 15:52:47 +05:00
Ivan Romanov
9e4bf79543 Fix install framework 2016-05-27 15:41:25 +05:00
Patrizio Bekerle
583d450885 fixed a typo 2016-03-17 11:03:42 +01:00
Samuel Gaist
f223ce03d4 OS X build and warning fix
The cmake find file was missing, but CoreFoundation being a system
framework, no need to search for it.

Update code to not use deprecated functions/data structure

CSSM_DATA and SecCertificateGetData have been deprecated since 10.7.
This patch uses SecCertificateCopyData which is the official
replacement.

Reviewed at https://git.reviewboard.kde.org/r/125800/
2015-12-08 21:32:39 +01:00
Rex Dieter
1ff36f4030 use _DEFAULT_SOURCE instead of _BSD_SOURCE
the former is used in other kde software in general, and
the latter is generally deprecated on modern glibc's
2015-11-19 13:23:16 -06:00
Ivan Romanov
4c9f27270e Add missed file
This file must be a part of 4fd11c444a51e8d317b0d68c7b90a8e0f2c6af9f
commit.

REVIEW: 121703
2015-11-18 23:54:14 +05:00
Ivan Romanov
69d8e070f0 Delete dead variable
className is not used. Furthemore it leads to possible crash when no _instance.
2015-11-11 12:35:10 +05:00
Ivan Romanov
da14be6f1b Fix empty strings in pluginPaths
Empty strings lead to strange behaviour and crashes.
2015-11-11 01:54:33 +05:00
Ivan Romanov
558f819819 gnupg: use utf-8 for keys output 2015-10-29 10:52:11 +05:00
Ivan Romanov
bf61f35cb4 gnupg: fixed keys is not updating
On Windows gpg uses ANSI codepage to output homedir and keyrings
paths. No way to output in utf-8. Gpg returns utf-8 strings output
only when --with-colons option is used.
2015-10-29 10:52:11 +05:00
Ivan Romanov
7e4192b70e gnupg: resolve symbolic links
Keyrings watcher can gets paths in any format. To avoid possible
problems try to use unified names for paths.
2015-10-29 10:52:11 +05:00
Ivan Romanov
7a76a9c027 qca-gnupg: default path to keyrings
When no keys 'gpg --list-keys' doesn't return path to keyring file.
Path is needest for watching to know when keys added or removed.
Use default keyrings path based on GnuPG home directory. This
directory gets with output 'gpg --version'. Line which starts with
'Home: ' contains GnuPG home directory. I believe it is correct
for GnuPG always and won't be changed in the future.
2015-10-29 10:52:11 +05:00
Heiko Becker
0dbed8eb38 qca-ossl: Fix build without support for SHA-0
LibreSSL >= 2.3.0 removed support for SHA-0, so there's no EVP_sha
anymore.
Wikipedia says about SHA-0: "160-bit hash function published in 1993
under the name SHA. It was withdrawn shortly after publication due to
an undisclosed "significant flaw" and replaced by the slightly revised
version SHA-1.'

REVIEW: 125387
2015-10-28 22:06:21 +01:00
Heiko Becker
20a587d776 qca-ossl: Fix build without SSLv3
This fixes building with LibreSSL >= 2.3.0 which has removed support
for SSLv3 completely. As far as I know OpenSSL can be configured to
build without it, so it might be helpful there as well.

REVIEW: 125386
2015-10-28 22:05:59 +01:00
Alon Bar-Lev
db17d5969b plugins: qca-logger: README: fix typo
Signed-off-by: Alon Bar-Lev <alon.barlev@gmail.com>
2015-10-23 22:32:07 +03:00
281 changed files with 62220 additions and 62875 deletions

3
.arcconfig Normal file
View File

@ -0,0 +1,3 @@
{
"phabricator.uri" : "https://phabricator.kde.org/"
}

99
.clang-format Normal file
View File

@ -0,0 +1,99 @@
# SPDX-License-Identifier: MIT
#
# Copyright (C) 2019 Christoph Cullmann <cullmann@kde.org>
# Copyright (C) 2019 Gernot Gebhard <gebhard@absint.com>
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# Style for C++
Language: Cpp
# base is WebKit coding style: https://webkit.org/code-style-guidelines/
# below are only things set that diverge from this style!
BasedOnStyle: WebKit
# enforce C++11 (e.g. for std::vector<std::vector<lala>>
Standard: Cpp11
# 4 spaces indent
TabWidth: 4
# good enough for 2 panes
ColumnLimit: 120
# sort includes inside line separated groups
SortIncludes: true
# Mostly 'Linux' style but with different enums
BreakBeforeBraces: Custom
BraceWrapping:
AfterEnum: true
AfterStruct: true
AfterClass: true
AfterCaseLabel: true
AfterFunction: true
# CrlInstruction *a;
PointerAlignment: Right
# horizontally aligns arguments after an open bracket.
AlignAfterOpenBracket: Align
# align trailing comments
AlignTrailingComments: true
# don't move all parameters to new line
AllowAllParametersOfDeclarationOnNextLine: false
# no single line functions
AllowShortFunctionsOnASingleLine: None
# always break before you encounter multi line strings
AlwaysBreakBeforeMultilineStrings: true
# don't move arguments to own lines if they are not all on the same
BinPackArguments: false
# don't move parameters to own lines if they are not all on the same
BinPackParameters: false
# don't break binary ops
BreakBeforeBinaryOperators: None
# format C++11 braced lists like function calls
Cpp11BracedListStyle: true
# remove empty lines
KeepEmptyLinesAtTheStartOfBlocks: false
# no namespace indentation to keep indent level low
NamespaceIndentation: None
# we use template< without space.
SpaceAfterTemplateKeyword: false
# macros for which the opening brace stays attached.
ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH, forever, Q_FOREVER, QBENCHMARK, QBENCHMARK_ONCE ]
# put all '=' in one column for consecutive lines
AlignConsecutiveAssignments: true
# put all the variables/constants names on the same column
AlignConsecutiveDeclarations: true

2
.git-blame-ignore-revs Normal file
View File

@ -0,0 +1,2 @@
# _clang_format added
f62a8ee8f7e81a1b573c335ded3326d8ee985ab4

50
.gitlab-ci.yml Normal file
View File

@ -0,0 +1,50 @@
build_ubuntu_20_10:
stage: build
image: ubuntu:groovy
before_script:
- sed -i -e 's/# deb-src/deb-src/g' /etc/apt/sources.list
- apt update
- apt install --yes eatmydata
- eatmydata apt build-dep --yes --no-install-recommends qca2
- eatmydata apt install --yes --no-install-recommends ninja-build libbotan-2-dev libnss3-dev libgcrypt20-dev libpkcs11-helper1-dev gnupg
script:
- mkdir -p build && cd build
- cmake -G Ninja ..
- ninja
- QT_PLUGIN_PATH=`pwd`/lib/qca-qt5/ ctest -V
build_fedora_34:
stage: build
image: fedora:34
before_script:
- dnf -y --setopt=install_weak_deps=False install git gcc-c++ make cmake ninja-build qt6-qtbase-devel qt6-qt5compat-devel botan2-devel cyrus-sasl-devel nss-devel libgcrypt-devel pkcs11-helper-devel gnupg
script:
- mkdir -p build && cd build
- cmake -G Ninja -DQT6=ON ..
- ninja
- QT_PLUGIN_PATH=`pwd`/lib/qca-qt6/ ctest -V
build_clazy_clang_tidy:
stage: build
image: debian:unstable
before_script:
- echo 'deb-src http://deb.debian.org/debian unstable main' >> /etc/apt/sources.list
- apt-get update
- apt-get install --yes eatmydata
- eatmydata apt-get build-dep --yes --no-install-recommends qca2
- eatmydata apt-get install --yes --no-install-recommends ninja-build libbotan-2-dev libnss3-dev libgcrypt20-dev libpkcs11-helper1-dev clazy clang clang-tidy jq gnupg
script:
- srcdir=`pwd` && mkdir -p /tmp/qca_build && cd /tmp/qca_build && CC=clang CXX=clazy CXXFLAGS="-Werror -Wno-deprecated-declarations" cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -G Ninja $srcdir && cat compile_commands.json | jq '[.[] | select(.file | contains("'"$srcdir"'"))]' > compile_commands.aux.json && mv compile_commands.aux.json compile_commands.json
- CLAZY_CHECKS="level0,level1,level2,no-copyable-polymorphic,no-ctor-missing-parent-argument,isempty-vs-count,qhash-with-char-pointer-key,qproperty-type-mismatch,qrequiredresult-candidates,signal-with-return-value,thread-with-slots,tr-non-literal,unneeded-cast" ninja
- "run-clang-tidy -header-filter='.*/qca/.*' -checks='-*,performance-*,modernize-deprecated-headers,modernize-make-unique,modernize-make-shared,modernize-use-override,modernize-use-equals-delete,modernize-use-emplace,modernize-use-bool-literals,modernize-redundant-void-arg,modernize-loop-convert,modernize-use-nullptr,-performance-no-automatic-move' -config=\"{WarningsAsErrors: '*'}\""
- QT_PLUGIN_PATH=`pwd`/lib/qca-qt5/ ctest -V
clang_format:
stage: build
image: debian:testing
before_script:
- apt-get update
- apt-get install --yes --no-install-recommends git clang-format-11
script:
- find . \( -name "*.cpp" -or -name "*.h" -or -name "*.c" -or -name "*.cc" \) -exec clang-format-11 -i {} \;
- git diff --exit-code

View File

@ -1,24 +1,25 @@
# Checking for user explicity defined CMAKE_INSTALL_PREFIX
# Checking for user explicitly defined CMAKE_INSTALL_PREFIX
# It must be done before project(...)
if(NOT CMAKE_INSTALL_PREFIX)
set(QCA_INSTALL_IN_QT_PREFIX ON)
# If CMAKE_INSTALL_PREFIX is set in cmake arguments
unset(CMAKE_INSTALL_PREFIX CACHE)
endif(NOT CMAKE_INSTALL_PREFIX)
endif()
# The cmake min. version should be set before calling project(...) too
cmake_minimum_required(VERSION 3.4)
project(qca)
cmake_minimum_required(VERSION 2.8.12)
set(QCA_LIB_MAJOR_VERSION "2")
set(QCA_LIB_MINOR_VERSION "1")
set(QCA_LIB_PATCH_VERSION "1")
set(QCA_LIB_MINOR_VERSION "3")
set(QCA_LIB_PATCH_VERSION "3")
# Do not automatically link Qt executables to qtmain target on Windows.
# QCA exucatables use console mode only. Not need to link against
# qtmain.lib.
cmake_policy(SET CMP0020 OLD)
#if(POLICY CMP0042)
# cmake_policy(SET CMP0042 OLD)
#endif()
option(QT6 "Build with Qt 6" OFF)
option(BUILD_TESTS "Create test" ON)
option(BUILD_TOOLS "Compile mozcerts and qcatool" ON)
set(BUILD_PLUGINS "auto" CACHE STRING "Plugins for building (also possible values: none, all and auto)")
@ -37,44 +38,32 @@ find_package(Doxygen)
string(TOLOWER "${BUILD_PLUGINS}" BUILD_PLUGINS)
if(NOT BUILD_PLUGINS)
set(BUILD_PLUGINS "none")
endif(NOT BUILD_PLUGINS)
endif()
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules" )
option(QT4_BUILD "Force building with Qt4 even if Qt5 is found")
if (NOT QT4_BUILD)
find_package(Qt5Core QUIET)
mark_as_advanced(Qt5Core_DIR)
# Do not automatically link Qt executables to qtmain target on Windows.
# QCA exucatables use console mode only. Not need to link against qtmain.lib.
if(QT6)
message(STATUS "Building Qt 6 version")
find_package(Qt6 COMPONENTS Core Test Core5Compat REQUIRED)
else()
message(STATUS "Building Qt 5 version")
set(Qt5_NO_LINK_QTMAIN ON)
find_package(Qt5 5.14 REQUIRED Core)
endif()
set(CMAKE_AUTOMOC ON)
include(QcaMacro)
if (Qt5Core_FOUND)
message(STATUS "Building with Qt5 support")
# Got from ECM
# Distros have no ECM. So I just copied required cmake modules.
find_package(Qt5Transitional REQUIRED Core Network)
include(ECMQt4To5Porting)
include(GNUInstallDirs)
setup_qt5_dirs()
include(GNUInstallDirs)
setup_qt_dirs()
if(QT6)
set(QCA_QT_PC_VERSION "Qt6Core")
set(QCA_SUFFIX "qt6")
else()
set(QCA_QT_PC_VERSION "Qt5Core")
set(QCA_SUFFIX "qt5")
else()
set(QT_MIN_VERSION "4.7.0")
set(QT_USE_IMPORTED_TARGETS ON)
if(BUILD_TESTS)
find_package(Qt4 REQUIRED QtCore QtNetwork QtTest)
else(BUILD_TESTS)
find_package(Qt4 REQUIRED QtCore)
endif(BUILD_TESTS)
# WORKAROUND: Seems it must be done in Qt4 find module but didn't
mark_as_advanced(QT_QMAKE_EXECUTABLE)
# properly set up compile flags (QT_DEBUG/QT_NO_DEBUG, ...)
include(${QT_USE_FILE})
setup_qt4_dirs()
set(QCA_QT_PC_VERSION "QtCore")
endif()
# QCA can be shared but plugins will be static
@ -83,9 +72,9 @@ if(NOT BUILD_SHARED_LIBS OR QT_IS_STATIC)
set(STATIC_PLUGINS ON)
add_definitions(-DQT_STATICPLUGIN)
set(PLUGIN_TYPE "STATIC")
else(NOT BUILD_SHARED_LIBS OR QT_IS_STATIC)
else()
set(PLUGIN_TYPE "MODULE")
endif(NOT BUILD_SHARED_LIBS OR QT_IS_STATIC)
endif()
set(QCA_SUFFIX "${QCA_SUFFIX}" CACHE STRING "QCA common suffix")
if(QCA_SUFFIX)
@ -94,13 +83,13 @@ if(QCA_SUFFIX)
set(MOZCERTS_NAME mozcerts-${QCA_SUFFIX})
set(QCA_PC_NAME qca2-${QCA_SUFFIX}.pc)
set(QCA_CONFIG_NAME_BASE "Qca-${QCA_SUFFIX}")
else(QCA_SUFFIX)
else()
set(QCA_LIB_NAME qca)
set(QCA_TOOL_NAME qcatool)
set(MOZCERTS_NAME mozcerts)
set(QCA_PC_NAME qca2.pc)
set(QCA_CONFIG_NAME_BASE "Qca")
endif(QCA_SUFFIX)
endif()
set(QCA_LIB_VERSION_STRING "${QCA_LIB_MAJOR_VERSION}.${QCA_LIB_MINOR_VERSION}.${QCA_LIB_PATCH_VERSION}")
@ -111,23 +100,42 @@ if (WIN32)
add_definitions(-DWIN32_LEAN_AND_MEAN)
elseif (APPLE)
set(CMAKE_DEBUG_POSTFIX "_debug")
endif (WIN32)
endif()
if (CMAKE_COMPILER_IS_GNUCXX)
if (CMAKE_CXX_COMPILER_ID MATCHES "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
if (CMAKE_SYSTEM_NAME MATCHES Linux)
add_definitions (-D_BSD_SOURCE)
add_definitions (-D_DEFAULT_SOURCE)
# on arm -Wcast-align throws many internal qt warning
if(NOT CMAKE_SYSTEM_PROCESSOR MATCHES "^arm")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wcast-align")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wcast-align")
endif()
set ( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-long-long -ansi -Wundef -Werror-implicit-function-declaration -Wchar-subscripts -Wall -W -Wpointer-arith -Wwrite-strings -Wformat-security -Wmissing-format-attribute -fno-common")
set ( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wnon-virtual-dtor -Wno-long-long -ansi -Wundef -Wchar-subscripts -Wall -W -Wpointer-arith -Wwrite-strings -Wformat-security -fno-check-new -fno-common")
endif (CMAKE_SYSTEM_NAME MATCHES Linux)
endif (CMAKE_COMPILER_IS_GNUCXX)
set ( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-long-long -Wundef -Werror-implicit-function-declaration -Wchar-subscripts -Wall -W -Wpointer-arith -Wwrite-strings -Wformat-security -Wmissing-format-attribute -fno-common")
set ( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wnon-virtual-dtor -Wno-long-long -Wundef -Wchar-subscripts -Wall -W -Wpointer-arith -Wwrite-strings -Wformat-security -fno-check-new -fno-common")
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wsuggest-override -Wlogical-op" )
endif()
endif()
endif()
add_definitions(-DQT_NO_CAST_TO_ASCII
-DQT_NO_CAST_FROM_ASCII
-DQT_NO_URL_CAST_FROM_STRING
-DQT_NO_CAST_FROM_BYTEARRAY
-DQT_NO_SIGNALS_SLOTS_KEYWORDS
-DQT_USE_QSTRINGBUILDER
-DQT_NO_NARROWING_CONVERSIONS_IN_CONNECT)
if (NOT WIN32)
# Strict iterators can't be used on Windows, they lead to a link error
# when application code iterates over a QVector<QPoint> for instance, unless
# Qt itself was also built with strict iterators.
# See example at https://bugreports.qt.io/browse/AUTOSUITE-946
add_definitions(-DQT_STRICT_ITERATORS)
endif()
add_definitions (${QT_DEFINITIONS})
include_directories("include/QtCrypto/")
# for generated files
include_directories(${CMAKE_BINARY_DIR})
@ -174,7 +182,7 @@ if( QCA_INSTALL_IN_QT_PREFIX )
endif()
set(QCA_DOC_INSTALL_DIR "${QT_DOC_DIR}/html/qca/" CACHE PATH "Directory where qca documentation will install")
set(QCA_MAN_INSTALL_DIR "${QT_DATA_DIR}/man" CACHE PATH "Directory where qca man pages will install")
else( QCA_INSTALL_IN_QT_PREFIX )
else()
# Cmake says nothing about LIB_SUFFIX
# de facto it is a standard way to specify lib suffix on many distros
set(LIB_SUFFIX "" CACHE STRING "Define suffix of directory name (32/64)" )
@ -194,12 +202,18 @@ else( QCA_INSTALL_IN_QT_PREFIX )
endif()
set(QCA_DOC_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/share/doc/${QCA_LIB_NAME}/html" CACHE PATH "Directory where qca documentation will install")
set(QCA_MAN_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/share/man" CACHE PATH "Directory where qca man pages will install")
endif( QCA_INSTALL_IN_QT_PREFIX )
endif()
set(PKGCONFIG_INSTALL_PREFIX "${QCA_LIBRARY_INSTALL_DIR}/pkgconfig" CACHE PATH "Base directory for pkgconfig files")
normalize_path(QCA_PREFIX_INSTALL_DIR)
if(OSX_FRAMEWORK)
set(QCA_FULL_INCLUDE_INSTALL_DIR "${QCA_LIBRARY_INSTALL_DIR}/${QCA_LIB_NAME}.framework/Headers")
else()
set(QCA_FULL_INCLUDE_INSTALL_DIR "${QCA_INCLUDE_INSTALL_DIR}/QtCrypto")
endif()
# check for oportunity to use relative paths
option(USE_RELATIVE_PATHS "Try to make relocatable package")
@ -225,19 +239,21 @@ endforeach()
if(NOT WIN32)
if(OSX_FRAMEWORK)
set(PKGCONFIG_CFLAGS "-F\${libdir} -I\${libdir}/${QCA_LIB_NAME}.framework/Headers")
set(PKGCONFIG_CFLAGS "-F\${libdir} -I\${includedir}")
set(PKGCONFIG_LIBS "-F\${libdir} -framework ${QCA_LIB_NAME}")
else()
set(PKGCONFIG_CFLAGS "-I\${includedir}")
set(PKGCONFIG_LIBS "-L\${libdir} -l${QCA_LIB_NAME}")
endif()
# qca2.pc uses absolute paths. So it must be there. Don't rellocate this.
configure_file("qca2.pc.cmake" "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/pkgconfig/${QCA_PC_NAME}" @ONLY)
if(NOT DEVELOPER_MODE)
install(FILES "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/pkgconfig/${QCA_PC_NAME}" DESTINATION ${PKGCONFIG_INSTALL_PREFIX})
if(NOT QT6)
# qca2.pc uses absolute paths. So it must be there. Don't rellocate this.
configure_file("qca2.pc.cmake" "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/pkgconfig/${QCA_PC_NAME}" @ONLY)
if(NOT DEVELOPER_MODE)
install(FILES "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/pkgconfig/${QCA_PC_NAME}" DESTINATION ${PKGCONFIG_INSTALL_PREFIX})
endif()
endif()
endif(NOT WIN32)
endif()
# strip CMAKE_INSTALL_PREFIX in all paths
if(USE_RELATIVE_PATHS)
@ -272,23 +288,19 @@ Plugins=${CMAKE_BINARY_DIR}/lib/${QCA_LIB_NAME}
endif()
if (APPLE)
find_package(CoreFoundation REQUIRED)
set(CMAKE_INSTALL_NAME_DIR ${QCA_LIBRARY_INSTALL_DIR})
set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
endif (APPLE)
endif()
message(STATUS "Checking for certstore..")
# fixme add OR mac
if( WIN32 )
# USE BUILTIN
else ( WIN32 )
# USE BUILTIN
else()
if ( DEFINED ENV{QC_CERTSTORE_PATH} )
if(EXISTS $ENV{QC_CERTSTORE_PATH})
set( qca_CERTSTORE $ENV{QC_CERTSTORE_PATH})
else(EXISTS $ENV{QC_CERTSTORE_PATH})
# path to try
endif(EXISTS $ENV{QC_CERTSTORE_PATH})
else( DEFINED ENV{QC_CERTSTORE_PATH} )
endif()
else()
set( toTry
"/etc/ssl/certs/ca-certificates.crt"
"/usr/share/ssl/cert.pem"
@ -300,28 +312,28 @@ else ( WIN32 )
foreach (_current_try ${toTry})
if(EXISTS ${_current_try})
set( qca_CERTSTORE ${_current_try})
endif(EXISTS ${_current_try})
endif()
endforeach (_current_try)
endif( DEFINED ENV{QC_CERTSTORE_PATH} )
endif(WIN32)
endif()
endif()
if (qca_CERTSTORE)
message(STATUS "Found system certstore")
else (qca_CERTSTORE)
else()
message(STATUS "Using built in certstore.")
set( qca_CERTSTORE "${CMAKE_CURRENT_SOURCE_DIR}/certs/rootcerts.pem")
# note that INSTALL_FILES targets are relative to the current installation prefix...
if(NOT DEVELOPER_MODE)
install(FILES "${qca_CERTSTORE}" DESTINATION "${QCA_PREFIX_INSTALL_DIR}/certs")
endif()
endif (qca_CERTSTORE)
endif()
message(STATUS "certstore path: " ${qca_CERTSTORE})
add_definitions( -DQCA_SYSTEMSTORE_PATH="${qca_CERTSTORE}" )
set( private_HEADERS ${qca_INCLUDEDIR}/QtCrypto/qca_plugin.h ${qca_INCLUDEDIR}/QtCrypto/qca_systemstore.h )
set( public_HEADERS
set( public_HEADERS
${qca_INCLUDEDIR}/QtCrypto/qca.h
${qca_INCLUDEDIR}/QtCrypto/qcaprovider.h
${qca_INCLUDEDIR}/QtCrypto/QtCrypto
@ -342,11 +354,13 @@ set( public_HEADERS
set( qca_HEADERS ${private_HEADERS} ${public_HEADERS} )
include_directories(${QT_QTCORE_INCLUDE_DIR} "${qca_INCLUDEDIR}/QtCrypto")
include_directories("${qca_INCLUDEDIR}/QtCrypto")
configure_file("crypto.prf.cmake" "${CMAKE_BINARY_DIR}/mkspecs/features/crypto.prf" @ONLY)
if(NOT DEVELOPER_MODE)
install(FILES "${CMAKE_BINARY_DIR}/mkspecs/features/crypto.prf" DESTINATION "${QCA_FEATURE_INSTALL_DIR}")
if(NOT QT6)
configure_file("crypto.prf.cmake" "${CMAKE_BINARY_DIR}/mkspecs/features/crypto.prf" @ONLY)
if(NOT DEVELOPER_MODE)
install(FILES "${CMAKE_BINARY_DIR}/mkspecs/features/crypto.prf" DESTINATION "${QCA_FEATURE_INSTALL_DIR}")
endif()
endif()
configure_file(man/qcatool.1 "${CMAKE_BINARY_DIR}/share/man/man1/${QCA_TOOL_NAME}.1" COPYONLY)
@ -366,29 +380,29 @@ if(STATIC_PLUGINS)
if(WITH_${PLUGIN}_PLUGIN_INTERNAL)
string(REPLACE "-" "_" IMPORT_NAME "qca-${PLUGIN}")
file(APPEND "${CMAKE_BINARY_DIR}/import_plugins.h" "Q_IMPORT_PLUGIN(${IMPORT_NAME})\n")
endif(WITH_${PLUGIN}_PLUGIN_INTERNAL)
endif()
endforeach(PLUGIN IN LISTS PLUGINS)
endif(STATIC_PLUGINS)
endif()
if(BUILD_TESTS)
enable_testing()
add_subdirectory(unittest)
add_subdirectory(examples)
endif(BUILD_TESTS)
endif()
if(BUILD_TOOLS)
add_subdirectory(tools)
endif(BUILD_TOOLS)
endif()
if(DOXYGEN_FOUND)
configure_file(${CMAKE_SOURCE_DIR}/Doxyfile.in ${CMAKE_BINARY_DIR}/Doxyfile @ONLY)
add_custom_target(doc
${DOXYGEN_EXECUTABLE} ${CMAKE_BINARY_DIR}/Doxyfile
COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/images
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_SOURCE_DIR}/images/qca-arch.eps ${CMAKE_BINARY_DIR}/images/qca-arch.eps
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_SOURCE_DIR}/images/qca-arch.png ${CMAKE_BINARY_DIR}/images/qca-arch.png
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
COMMENT "Generating API documentation with Doxygen" VERBATIM)
endif(DOXYGEN_FOUND)
#if(DOXYGEN_FOUND)
# configure_file(${CMAKE_SOURCE_DIR}/Doxyfile.in ${CMAKE_BINARY_DIR}/Doxyfile @ONLY)
# add_custom_target(doc
# ${DOXYGEN_EXECUTABLE} ${CMAKE_BINARY_DIR}/Doxyfile
# COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/docs/pics
# COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_SOURCE_DIR}/docs/pics/qca-arch.eps ${CMAKE_BINARY_DIR}/docs/pics/qca-arch.eps
# COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_SOURCE_DIR}/docs/pics/qca-arch.png ${CMAKE_BINARY_DIR}/docs/pics/qca-arch.png
# WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
# COMMENT "Generating API documentation with Doxygen" VERBATIM)
#endif()
include(CMakePackageConfigHelpers)
configure_package_config_file(
@ -418,7 +432,7 @@ if(NOT DEVELOPER_MODE)
message("!! you MUST explicity define CMAKE_INSTALL_PREFIX !!")
message("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")
message("${ESCAPE}[0m")
endif(QCA_INSTALL_IN_QT_PREFIX)
endif()
message("")
if(USE_RELATIVE_PATHS)
@ -455,11 +469,16 @@ if(NOT DEVELOPER_MODE)
message("")
if(UNIX AND NOT APPLE)
if(NOT QCA_SUFFIX AND NOT QT4_BUILD)
if(NOT QCA_SUFFIX)
message("${ESCAPE}[31mYou don't have QCA_SUFFIX set. Please note that the recommended way of")
message("building Qt5 version of qca for Linux distributions is to set")
message("QCA_SUFFIX to qt5 (-DQCA_SUFFIX=qt5).")
if(QT6)
message("building Qt6 version of qca for Linux distributions is to set")
message("QCA_SUFFIX to qt6 (-DQCA_SUFFIX=qt6).")
else()
message("building Qt5 version of qca for Linux distributions is to set")
message("QCA_SUFFIX to qt5 (-DQCA_SUFFIX=qt5).")
endif()
message("${ESCAPE}[0m")
endif()
endif()

View File

@ -567,7 +567,7 @@ EXAMPLE_RECURSIVE = NO
# directories that contain image that are included in the documentation (see
# the \image command).
IMAGE_PATH = @CMAKE_SOURCE_DIR@/images
IMAGE_PATH = @CMAKE_SOURCE_DIR@/docs/pics
# The INPUT_FILTER tag can be used to specify a program that doxygen should
# invoke to filter for each input file. Doxygen will invoke the filter program
@ -1070,7 +1070,7 @@ PREDEFINED = DOXYGEN_SHOULD_SKIP_THIS \
# The macro definition that is found in the sources will be used.
# Use the PREDEFINED tag if you want to use a different macro definition.
EXPAND_AS_DEFINED = QCA_EXPORT
EXPAND_AS_DEFINED = QCA_EXPORT QCA_NOEXCEPT
# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
# doxygen's preprocessor will remove all function-like macros that are alone

11
INSTALL
View File

@ -1,7 +1,7 @@
Installing QCA
--------------
QCA requires Qt 4.7 or greater.
QCA requires Qt 5.5 or greater.
For Unix/Linux/Mac/Windows:
@ -17,7 +17,6 @@ Notes
CMAKE_INSTALL_PREFIX - must be defined otherwise QCA will be installed
in Qt prefix (by default: "")
QT4_BUILD - forced Qt4 building (by default: OFF)
BUILD_TESTS - build unittests (by default: ON)
BUILD_TOOLS - build mozcerts and qcatool (by default: ON)
QCA_SUFFIX - suffix will be used for library, qcatool binary,
@ -53,10 +52,4 @@ Please report problems to:
http://bugs.kde.org
Official git repo:
http://quickgit.kde.org/?p=qca.git
KDE Projects page:
http://projects.kde.org/projects/kdesupport/qca
Official homepage:
http://delta.affinix.com/qca/
https://invent.kde.org/kde/qca

View File

@ -150,9 +150,9 @@
\subsection qca2code Releases
The latest release packages can be found in the
<a href="http://delta.affinix.com/download/qca/2.0/">%QCA 2.0 download area</a>.
<a href="https://download.kde.org/stable/qca/">%QCA 2.x download area</a>.
See the <a href="http://delta.affinix.com/qca/">project web site</a> for
See the <a href="https://userbase.kde.org/QCA/">project web site</a> for
further information about %QCA releases.
\subsection qca2dev Current development
@ -163,12 +163,12 @@
to build and use %QCA.
The Git code can be browsed
<a href="http://quickgit.kde.org/?p=qca.git">
<a href="https://commits.kde.org/qca">
via the web</a>
Use
\verbatim
git clone git://anongit.kde.org/qca.git
git clone https://invent.kde.org/libraries/qca.git
\endverbatim
to get the latest sources.
*/

View File

@ -1,7 +1,7 @@
@PACKAGE_INIT@
if(NOT TARGET @QCA_CONFIG_NAME_BASE@)
if(NOT TARGET @QCA_LIB_NAME@)
include("${CMAKE_CURRENT_LIST_DIR}/@QCA_CONFIG_NAME_BASE@Targets.cmake")
endif()
set(Qca_LIBRARY @QCA_CONFIG_NAME_BASE@)
set(Qca_LIBRARY @QCA_LIB_NAME@)

77
README
View File

@ -1,26 +1,19 @@
Qt Cryptographic Architecture (QCA) version 2.1.0
-------------------------------------------------
Date: November 6th, 2014
Website: http://delta.affinix.com/qca/
Mailing List: Delta Project <delta@lists.affinix.com>
Qt Cryptographic Architecture (QCA)
-----------------------------------
Project Lead/Maintainer (2003-current):
Justin Karneges <justin@affinix.com>
(March 2007 - August 2007 under Barracuda Networks employment)
Description
-----------
Development, Documentation, Unittests (2004-2009):
Brad Hards <bradh@frogmouth.net>
QCA is a library that provides an easy API for a range of cryptographic
features, including SSL/TLS, X.509 certificates, SASL, OpenPGP, smartcards,
and much more.
Development (2013-current)
Ivan Romanov <drizt@land.ru>
Functionality is supplied via plugins. This is useful for avoiding
dependence on a particular crypto library and makes upgrading easier,
as there is no need to recompile your application when adding or
upgrading a crypto plugin.
Special Thanks:
Portugal Telecom (SAPO division), for sponsorship
Alon Bar-Lev, for smart card and design assistance
Jack Lloyd, for Botan and X.509 mentoring
L. Peter Deutsch, for the public domain MD5 implementation
Steve Reid, for the public domain SHA1 implementation
Jason Kim, for the CMS Signer graphics
In order for QCA to be of much use, you'll want to install some plugins.
Install
@ -34,10 +27,18 @@ License
the COPYING file for more information.
Changes
History
-------
QCA was originally created to support the security needs of the
Psi XMPP/Jabber client project ( http://psi-im.org/ ).
Old Changes list
----------------
New in 2.1.0
- Ported to Qt5 (Qt4 alsa supported)
- Ported to Qt5 (Qt4 also supported)
- New building system. CMake instead of qmake
- Added CTR symetric cipher support to qca core
- Added no padding encryption algorithm to qca core
@ -90,25 +91,23 @@ Changes
- Windows version can be configured/installed using paths with spaces
Description
-----------
Old Developer list
------------------
QCA is a library that provides an easy API for a range of cryptographic
features, including SSL/TLS, X.509 certificates, SASL, OpenPGP, smartcards,
and much more.
Project Lead/Maintainer (2003-2012):
Justin Karneges <justin@affinix.com>
(March 2007 - August 2007 under Barracuda Networks employment)
Functionality is supplied via plugins. This is useful for avoiding
dependence on a particular crypto library and makes upgrading easier,
as there is no need to recompile your application when adding or
upgrading a crypto plugin.
Development, Documentation, Unittests (2004-2009):
Brad Hards <bradh@frogmouth.net>
In order for QCA to be of much use, you'll want to install some plugins.
Development (2013-2017)
Ivan Romanov <drizt@land.ru>
QCA was originally created to support the security needs of the
Psi XMPP/Jabber client project ( http://psi-im.org/ ).
API Documentation is located in the 'apidocs' subdirectory.
Have fun,
-Justin
Special Thanks:
Portugal Telecom (SAPO division), for sponsorship
Alon Bar-Lev, for smart card and design assistance
Jack Lloyd, for Botan and X.509 mentoring
L. Peter Deutsch, for the public domain MD5 implementation
Steve Reid, for the public domain SHA1 implementation
Jason Kim, for the CMS Signer graphics

14
README.clang-format Normal file
View File

@ -0,0 +1,14 @@
We introduced clang-format mandatory usage in September 2020.
If you want git blame to ignore the revision in which we did the mass change you can do
git config blame.ignoreRevsFile .git-blame-ignore-revs
on your clone
To get the clang-format warnings locally instead at CI time we recommend you
to copy the hooks/pre-commit to your .git
cp hooks/pre-commit .git/hooks/
We are using clang-format 11 on CI. Unfortunately clang-format is not totally
compatible with older versions of itself. If CI gives you trouble but your local
clang-format disagrees, just apply the changes suggested by CI and then commit
with the --no-verify flag. If you get stuck, don't hesitate to ask the reviewer
to help and they will reformat your commits :)

View File

@ -1,5 +1,5 @@
rootcerts.pem is created by qca/tools/mozcerts
File: mozilla/security/nss/lib/ckfw/builtins/certdata.txt
Date: January 15th, 2009
File: https://hg.mozilla.org/mozilla-central/log/tip/security/nss/lib/ckfw/builtins/certdata.txt
Date: July 4, 2020

File diff suppressed because it is too large Load Diff

View File

@ -1,238 +0,0 @@
#=============================================================================
# Copyright 2005-2011 Kitware, Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# * Neither the name of Kitware, Inc. nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "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 COPYRIGHT
# HOLDER OR CONTRIBUTORS 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.
#=============================================================================
# The automoc_qt4 macro is superceded by CMAKE_AUTOMOC from CMake 2.8.6
# A Qt 5 version is not provided by CMake or Qt.
include(MacroAddFileDependencies)
MACRO (QT4_GET_MOC_FLAGS _moc_flags)
SET(${_moc_flags})
GET_DIRECTORY_PROPERTY(_inc_DIRS INCLUDE_DIRECTORIES)
FOREACH(_current ${_inc_DIRS})
IF("${_current}" MATCHES "\\.framework/?$")
STRING(REGEX REPLACE "/[^/]+\\.framework" "" framework_path "${_current}")
SET(${_moc_flags} ${${_moc_flags}} "-F${framework_path}")
ELSE("${_current}" MATCHES "\\.framework/?$")
SET(${_moc_flags} ${${_moc_flags}} "-I${_current}")
ENDIF("${_current}" MATCHES "\\.framework/?$")
ENDFOREACH(_current ${_inc_DIRS})
GET_DIRECTORY_PROPERTY(_defines COMPILE_DEFINITIONS)
FOREACH(_current ${_defines})
SET(${_moc_flags} ${${_moc_flags}} "-D${_current}")
ENDFOREACH(_current ${_defines})
IF(Q_WS_WIN)
SET(${_moc_flags} ${${_moc_flags}} -DWIN32)
ENDIF(Q_WS_WIN)
ENDMACRO(QT4_GET_MOC_FLAGS)
# helper macro to set up a moc rule
MACRO (QT4_CREATE_MOC_COMMAND infile outfile moc_flags moc_options)
# For Windows, create a parameters file to work around command line length limit
IF (WIN32)
# Pass the parameters in a file. Set the working directory to
# be that containing the parameters file and reference it by
# just the file name. This is necessary because the moc tool on
# MinGW builds does not seem to handle spaces in the path to the
# file given with the @ syntax.
GET_FILENAME_COMPONENT(_moc_outfile_name "${outfile}" NAME)
GET_FILENAME_COMPONENT(_moc_outfile_dir "${outfile}" PATH)
IF(_moc_outfile_dir)
SET(_moc_working_dir WORKING_DIRECTORY ${_moc_outfile_dir})
ENDIF(_moc_outfile_dir)
SET (_moc_parameters_file ${outfile}_parameters)
SET (_moc_parameters ${moc_flags} ${moc_options} -o "${outfile}" "${infile}")
STRING (REPLACE ";" "\n" _moc_parameters "${_moc_parameters}")
FILE (WRITE ${_moc_parameters_file} "${_moc_parameters}")
ADD_CUSTOM_COMMAND(OUTPUT ${outfile}
COMMAND ${QT_MOC_EXECUTABLE} @${_moc_outfile_name}_parameters
DEPENDS ${infile}
${_moc_working_dir}
VERBATIM)
ELSE (WIN32)
ADD_CUSTOM_COMMAND(OUTPUT ${outfile}
COMMAND ${QT_MOC_EXECUTABLE}
ARGS ${moc_flags} ${moc_options} -o ${outfile} ${infile}
DEPENDS ${infile} VERBATIM)
ENDIF (WIN32)
ENDMACRO (QT4_CREATE_MOC_COMMAND)
MACRO(QT4_AUTOMOC)
QT4_GET_MOC_FLAGS(_moc_INCS)
SET(_matching_FILES )
FOREACH (_current_FILE ${ARGN})
GET_FILENAME_COMPONENT(_abs_FILE ${_current_FILE} ABSOLUTE)
# if "SKIP_AUTOMOC" is set to true, we will not handle this file here.
# This is required to make uic work correctly:
# we need to add generated .cpp files to the sources (to compile them),
# but we cannot let automoc handle them, as the .cpp files don't exist yet when
# cmake is run for the very first time on them -> however the .cpp files might
# exist at a later run. at that time we need to skip them, so that we don't add two
# different rules for the same moc file
GET_SOURCE_FILE_PROPERTY(_skip ${_abs_FILE} SKIP_AUTOMOC)
IF ( NOT _skip AND EXISTS ${_abs_FILE} )
FILE(READ ${_abs_FILE} _contents)
GET_FILENAME_COMPONENT(_abs_PATH ${_abs_FILE} PATH)
STRING(REGEX MATCHALL "# *include +[^ ]+\\.moc[\">]" _match "${_contents}")
IF(_match)
FOREACH (_current_MOC_INC ${_match})
STRING(REGEX MATCH "[^ <\"]+\\.moc" _current_MOC "${_current_MOC_INC}")
GET_FILENAME_COMPONENT(_basename ${_current_MOC} NAME_WE)
IF(EXISTS ${_abs_PATH}/${_basename}.hpp)
SET(_header ${_abs_PATH}/${_basename}.hpp)
ELSE(EXISTS ${_abs_PATH}/${_basename}.hpp)
SET(_header ${_abs_PATH}/${_basename}.h)
ENDIF(EXISTS ${_abs_PATH}/${_basename}.hpp)
SET(_moc ${CMAKE_CURRENT_BINARY_DIR}/${_current_MOC})
QT4_CREATE_MOC_COMMAND(${_header} ${_moc} "${_moc_INCS}" "")
MACRO_ADD_FILE_DEPENDENCIES(${_abs_FILE} ${_moc})
ENDFOREACH (_current_MOC_INC)
ENDIF(_match)
ENDIF ( NOT _skip AND EXISTS ${_abs_FILE} )
ENDFOREACH (_current_FILE)
ENDMACRO(QT4_AUTOMOC)
# Portability helpers.
set(QT_QTGUI_LIBRARIES
${Qt5Gui_LIBRARIES}
${Qt5Widgets_LIBRARIES}
${Qt5PrintSupport_LIBRARIES}
${Qt5Svg_LIBRARIES}
)
set(QT_INCLUDES
${Qt5Gui_INCLUDE_DIRS}
${Qt5Widgets_INCLUDE_DIRS}
${Qt5PrintSupport_INCLUDE_DIRS}
${Qt5Svg_INCLUDE_DIRS}
)
set(QT_QTGUI_LIBRARY ${QT_QTGUI_LIBRARIES})
set(_qt_modules
Core
Declarative
Widgets
Script
ScriptTools
DBus
Network
Test
Designer
Concurrent
Xml
UiTools
Qml
Quick1
WebKit
WebKitWidgets
Sql
OpenGL
)
foreach(_module ${_qt_modules})
string(TOUPPER ${_module} _module_upper)
set(QT_QT${_module_upper}_LIBRARIES ${Qt5${_module}_LIBRARIES})
set(QT_QT${_module_upper}_LIBRARY ${QT_QT${_module_upper}_LIBRARIES})
list(APPEND QT_INCLUDES ${Qt5${_module}_INCLUDE_DIRS})
set(QT_QT${_module_upper}_FOUND ${Qt5${_module}_FOUND})
endforeach()
list(APPEND QT_QTCORE_LIBRARIES ${Qt5Concurrent_LIBRARIES})
list(APPEND QT_QTCORE_LIBRARY ${Qt5Concurrent_LIBRARIES})
list(APPEND QT_QTWEBKIT_LIBRARIES ${Qt5WebKitWidgets_LIBRARIES})
list(APPEND QT_QTWEBKIT_LIBRARY ${Qt5WebKitWidgets_LIBRARIES})
set(QT_QTDECLARATIVE_LIBRARIES ${Qt5Quick1_LIBRARIES})
set(QT_QTDECLARATIVE_LIBRARY ${Qt5Quick1_LIBRARIES})
get_target_property(QT_QMAKE_EXECUTABLE Qt5::qmake LOCATION)
get_target_property(QT_RCC_EXECUTABLE Qt5::rcc LOCATION)
if (TARGET Qt5::uic)
get_target_property(QT_UIC_EXECUTABLE Qt5::uic LOCATION)
endif()
if (TARGET Qt5::qdbuscpp2xml)
get_target_property(QT_QDBUSCPP2XML_EXECUTABLE Qt5::qdbuscpp2xml LOCATION)
endif()
if (TARGET Qt5::qdbusxml2cpp)
get_target_property(QT_QDBUSXML2CPP_EXECUTABLE Qt5::qdbusxml2cpp LOCATION)
endif()
add_definitions(-DQT_DISABLE_DEPRECATED_BEFORE=0)
macro(qt4_wrap_ui)
qt5_wrap_ui(${ARGN})
endmacro()
macro(qt4_wrap_cpp)
qt5_wrap_cpp(${ARGN})
endmacro()
macro(qt4_generate_moc)
qt5_generate_moc(${ARGN})
endmacro()
macro(qt4_add_dbus_adaptor)
qt5_add_dbus_adaptor(${ARGN})
endmacro()
macro(qt4_add_dbus_interfaces)
qt5_add_dbus_interfaces(${ARGN})
endmacro()
macro(qt4_add_dbus_interface)
qt5_add_dbus_interface(${ARGN})
endmacro()
macro(qt4_generate_dbus_interface)
qt5_generate_dbus_interface(${ARGN})
endmacro()
macro(qt4_add_resources)
qt5_add_resources(${ARGN})
endmacro()

View File

@ -1,49 +0,0 @@
# - Try to find the Gcrypt library
# Once run this will define
#
# BOTAN_FOUND - set if the system has the gcrypt library
# BOTAN_CFLAGS - the required gcrypt compilation flags
# BOTAN_LIBRARIES - the linker libraries needed to use the gcrypt library
#
# Copyright (c) 2006 Brad Hards <bradh@kde.org>
#
# Redistribution and use is allowed according to the terms of the BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
# libgcrypt is moving to pkg-config, but earlier version don't have it
#search in typical paths for libgcrypt-config
FIND_PROGRAM(BOTANCONFIG_EXECUTABLE NAMES botan-config botan-config-1.10)
mark_as_advanced(BOTANCONFIG_EXECUTABLE)
#reset variables
set(BOTAN_LIBRARIES)
set(BOTAN_CFLAGS)
# if botan-config has been found
IF(BOTANCONFIG_EXECUTABLE)
EXEC_PROGRAM(${BOTANCONFIG_EXECUTABLE} ARGS --libs RETURN_VALUE _return_VALUE OUTPUT_VARIABLE BOTAN_LIBRARIES)
EXEC_PROGRAM(${BOTANCONFIG_EXECUTABLE} ARGS --cflags RETURN_VALUE _return_VALUE OUTPUT_VARIABLE BOTAN_CFLAGS)
IF(BOTAN_LIBRARIES)
SET(BOTAN_FOUND TRUE)
ENDIF(BOTAN_LIBRARIES)
MARK_AS_ADVANCED(BOTAN_CFLAGS BOTAN_LIBRARIES)
ENDIF(BOTANCONFIG_EXECUTABLE)
if (BOTAN_FOUND)
if (NOT Botan_FIND_QUIETLY)
message(STATUS "Found Botan: ${BOTAN_LIBRARIES}")
endif (NOT Botan_FIND_QUIETLY)
else (BOTAN_FOUND)
if (Botan_FIND_REQUIRED)
message(FATAL_ERROR "Could not find Botan libraries")
endif (Botan_FIND_REQUIRED)
endif (BOTAN_FOUND)

View File

@ -42,11 +42,11 @@ ENDIF(LIBGCRYPTCONFIG_EXECUTABLE)
if (LIBGCRYPT_FOUND)
if (NOT LibGcrypt_FIND_QUIETLY)
message(STATUS "Found libgcrypt: ${LIBGCRYPT_LIBRARIES}")
endif (NOT LibGcrypt_FIND_QUIETLY)
else (LIBGCRYPT_FOUND)
endif()
else()
if (LibGcrypt_FIND_REQUIRED)
message(FATAL_ERROR "Could not find libgcrypt libraries")
endif (LibGcrypt_FIND_REQUIRED)
endif (LIBGCRYPT_FOUND)
endif()
endif()
MARK_AS_ADVANCED(LIBGCRYPT_CFLAGS LIBGCRYPT_LIBRARIES)

View File

@ -1,37 +0,0 @@
# - Try to find the NSS library
# Once done this will define
#
# NSS_FOUND - system has mozilla-nss lib
# NSS_INCLUDE_DIRS - the mozilla-nss include directories
# NSS_LDFLAGS - Link these to use mozilla-nss
# NSS_CFLAGS_OTHER - Compiler switches required for using NSS
#
# Copyright (c) 2006, Laurent Montel, <montel@kde.org>
#
# Redistribution and use is allowed according to the terms of the BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
if(NSS_INCLUDE_DIRS AND NSS_LDFLAGS)
# in cache already
SET(NSS_FOUND TRUE)
else()
if(NOT WIN32)
find_package(PkgConfig)
pkg_search_module(NSS nss)
endif(NOT WIN32)
if (NSS_FOUND)
if (NOT Nss_FIND_QUIETLY)
message(STATUS "Found NSS: ${NSS_LDFLAGS}")
endif (NOT Nss_FIND_QUIETLY)
else (NSS_FOUND)
if (Nss_FIND_REQUIRED)
message(FATAL_ERROR "Could NOT find NSS")
endif (Nss_FIND_REQUIRED)
endif (NSS_FOUND)
mark_as_advanced(NSS_INCLUDE_DIRS NSS_LDFLAGS NSS_CFLAGS_OTHER)
endif()

View File

@ -23,17 +23,17 @@ else()
if(NOT WIN32)
find_package(PkgConfig)
pkg_search_module(PKCS11H libpkcs11-helper-1)
endif(NOT WIN32)
endif()
if (PKCS11H_FOUND)
if (NOT Pkcs11Helper_FIND_QUIETLY)
message(STATUS "Found pkcs11-helper: ${PKCS11H_LDFLAGS}")
endif (NOT Pkcs11Helper_FIND_QUIETLY)
else (PKCS11H_FOUND)
endif()
else()
if (Pkcs11Helper_FIND_REQUIRED)
message(FATAL_ERROR "Could NOT find pkcs11-helper")
endif (Pkcs11Helper_FIND_REQUIRED)
endif (PKCS11H_FOUND)
endif()
endif()
mark_as_advanced(PKCS11H_INCLUDE_DIRS PKCS11H_LDFLAGS PKCS11H_CFLAGS_OTHER)

View File

@ -1,125 +0,0 @@
find_package(Qt5Core QUIET)
mark_as_advanced(Qt5Core_DIR)
if (Qt5Core_FOUND)
if (NOT Qt5Transitional_FIND_COMPONENTS)
set(_components
Core
Gui
DBus
Designer
Declarative
Script
ScriptTools
Network
Test
Xml
Svg
Sql
Widgets
PrintSupport
Concurrent
UiTools
WebKit
WebKitWidgets
OpenGL
)
foreach(_component ${_components})
find_package(Qt5${_component})
mark_as_advanced(Qt5${_component}_DIR)
list(APPEND QT_LIBRARIES ${Qt5${_component}_LIBRARIES})
endforeach()
else()
set(_components ${Qt5Transitional_FIND_COMPONENTS})
foreach(_component ${Qt5Transitional_FIND_COMPONENTS})
find_package(Qt5${_component} REQUIRED)
mark_as_advanced(Qt5${_component}_DIR)
if ("${_component}" STREQUAL "WebKit")
find_package(Qt5WebKitWidgets REQUIRED)
mark_as_advanced(Qt5WebKitWidgets_DIR)
list(APPEND QT_LIBRARIES ${Qt5WebKitWidgets_LIBRARIES} )
endif()
if ("${_component}" STREQUAL "Gui")
find_package(Qt5Widgets REQUIRED)
find_package(Qt5PrintSupport REQUIRED)
find_package(Qt5Svg REQUIRED)
mark_as_advanced(Qt5Widgets_DIR Qt5PrintSupport_DIR Qt5Svg_DIR)
list(APPEND QT_LIBRARIES ${Qt5Widgets_LIBRARIES}
${Qt5PrintSupport_LIBRARIES}
${Qt5Svg_LIBRARIES} )
endif()
# Core module was separated to Core and Concurrent in Qt5.
# But QCA doesn't use any classes from QtConcurrent.
# So QtConcurrent mustn't be used in QCA.
# Uncomment this if Concurrent support will be added.
# if ("${_component}" STREQUAL "Core")
# find_package(Qt5Concurrent REQUIRED)
# list(APPEND QT_LIBRARIES ${Qt5Concurrent_LIBRARIES} )
# endif()
endforeach()
endif()
set(Qt5Transitional_FOUND TRUE)
set(QT5_BUILD TRUE)
# Temporary until upstream does this:
foreach(_component ${_components})
if (TARGET Qt5::${_component})
set_property(TARGET Qt5::${_component}
APPEND PROPERTY
INTERFACE_INCLUDE_DIRECTORIES ${Qt5${_component}_INCLUDE_DIRS})
set_property(TARGET Qt5::${_component}
APPEND PROPERTY
INTERFACE_COMPILE_DEFINITIONS ${Qt5${_component}_COMPILE_DEFINITIONS})
endif()
endforeach()
set_property(TARGET Qt5::Core
PROPERTY
INTERFACE_POSITION_INDEPENDENT_CODE ON
)
if (WIN32 AND NOT Qt5_NO_LINK_QTMAIN)
set(_isExe $<STREQUAL:$<TARGET_PROPERTY:TYPE>,EXECUTABLE>)
set(_isWin32 $<BOOL:$<TARGET_PROPERTY:WIN32_EXECUTABLE>>)
set(_isNotExcluded $<NOT:$<BOOL:$<TARGET_PROPERTY:Qt5_NO_LINK_QTMAIN>>>)
get_target_property(_configs Qt5::Core IMPORTED_CONFIGURATIONS)
foreach(_config ${_configs})
set_property(TARGET Qt5::Core APPEND PROPERTY
IMPORTED_LINK_INTERFACE_LIBRARIES_${_config}
$<$<AND:${_isExe},${_isWin32},${_isNotExcluded}>:Qt5::WinMain>
)
endforeach()
unset(_configs)
unset(_isExe)
unset(_isWin32)
unset(_isNotExcluded)
endif()
# End upstreamed stuff.
get_filename_component(_modules_dir "${CMAKE_CURRENT_LIST_DIR}/../modules" ABSOLUTE)
include("${_modules_dir}/ECMQt4To5Porting.cmake") # TODO: Port away from this.
include_directories(${QT_INCLUDES}) # TODO: Port away from this.
if (Qt5_POSITION_INDEPENDENT_CODE)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
endif()
else()
foreach(_component ${Qt5Transitional_FIND_COMPONENTS})
if("${_component}" STREQUAL "Widgets") # new in Qt5
set(_component Gui)
elseif("${_component}" STREQUAL "Concurrent") # new in Qt5
set(_component Core)
endif()
list(APPEND _components Qt${_component})
endforeach()
find_package(Qt4 ${QT_MIN_VERSION} REQUIRED ${_components})
include_directories(${QT_INCLUDES})
if(QT4_FOUND)
set(Qt5Transitional_FOUND TRUE)
endif()
endif()

View File

@ -14,7 +14,7 @@
if (SASL2_INCLUDE_DIR)
# Already in cache, be silent
set(SASL2_FIND_QUIETLY TRUE)
endif (SASL2_INCLUDE_DIR)
endif()
FIND_PATH(SASL2_INCLUDE_DIR sasl/sasl.h)
@ -23,18 +23,18 @@ FIND_LIBRARY(SASL2_LIBRARIES NAMES sasl2)
if (SASL2_INCLUDE_DIR AND SASL2_LIBRARIES)
set(SASL2_FOUND TRUE)
endif (SASL2_INCLUDE_DIR AND SASL2_LIBRARIES)
endif()
if (SASL2_FOUND)
if (NOT Sasl2_FIND_QUIETLY)
message(STATUS "Found Sasl2: ${SASL2_LIBRARIES}")
endif (NOT Sasl2_FIND_QUIETLY)
else (SASL2_FOUND)
endif()
else()
if (Sasl2_FIND_REQUIRED)
message(FATAL_ERROR "Could not find sasl2 libraries")
endif (Sasl2_FIND_REQUIRED)
endif (SASL2_FOUND)
endif()
endif()
MARK_AS_ADVANCED(SASL2_INCLUDE_DIR SASL2_LIBRARIES)

View File

@ -1,63 +1,28 @@
IF (Qt5Core_FOUND)
# FindQt4.cmake wasn't used, so define it here
MACRO (QT4_GET_MOC_INC_DIRS _moc_INC_DIRS)
SET(${_moc_INC_DIRS})
GET_DIRECTORY_PROPERTY(_inc_DIRS INCLUDE_DIRECTORIES)
FOREACH(_current ${_inc_DIRS})
SET(${_moc_INC_DIRS} ${${_moc_INC_DIRS}} "-I" ${_current})
ENDFOREACH(_current ${_inc_DIRS})
ENDMACRO(QT4_GET_MOC_INC_DIRS)
MACRO(SETUP_QT5_DIRS)
MACRO(SETUP_QT_DIRS)
if(QT6)
GET_TARGET_PROPERTY(QMAKE_EXECUTABLE Qt6::qmake LOCATION)
else()
GET_TARGET_PROPERTY(QMAKE_EXECUTABLE ${Qt5Core_QMAKE_EXECUTABLE} LOCATION)
EXEC_PROGRAM( ${QMAKE_EXECUTABLE} ARGS "-query QT_INSTALL_LIBS" OUTPUT_VARIABLE QT_LIBRARY_DIR )
EXEC_PROGRAM( ${QMAKE_EXECUTABLE} ARGS "-query QT_INSTALL_PREFIX" OUTPUT_VARIABLE QT_PREFIX_DIR )
EXEC_PROGRAM( ${QMAKE_EXECUTABLE} ARGS "-query QT_INSTALL_PLUGINS" OUTPUT_VARIABLE QT_PLUGINS_DIR )
EXEC_PROGRAM( ${QMAKE_EXECUTABLE} ARGS "-query QT_INSTALL_BINS" OUTPUT_VARIABLE QT_BINARY_DIR )
EXEC_PROGRAM( ${QMAKE_EXECUTABLE} ARGS "-query QT_INSTALL_HEADERS" OUTPUT_VARIABLE QT_HEADERS_DIR )
EXEC_PROGRAM( ${QMAKE_EXECUTABLE} ARGS "-query QT_INSTALL_DOCS" OUTPUT_VARIABLE QT_DOC_DIR )
EXEC_PROGRAM( ${QMAKE_EXECUTABLE} ARGS "-query QT_INSTALL_DATA" OUTPUT_VARIABLE QT_DATA_DIR )
EXEC_PROGRAM( ${QMAKE_EXECUTABLE} ARGS "-query QT_INSTALL_ARCHDATA" OUTPUT_VARIABLE QT_ARCHDATA_DIR )
SET( QT_MKSPECS_DIR "${QT_ARCHDATA_DIR}/mkspecs" )
ENDMACRO(SETUP_QT5_DIRS)
ELSE (Qt5Core_FOUND)
# Cmake FindQt4 module doesn't provide QT_INSTALL_PREFIX and QT_INSTALL_DATA vars
# It will be done here
MACRO(SETUP_QT4_DIRS)
_qt4_query_qmake(QT_INSTALL_PREFIX QT_PREFIX_DIR)
_qt4_query_qmake(QT_INSTALL_DATA QT_DATA_DIR)
ENDMACRO(SETUP_QT4_DIRS)
ENDIF()
MACRO(MY_AUTOMOC _srcsList)
# QT4_GET_MOC_INC_DIRS(_moc_INCS)
FOREACH (_current_FILE ${${_srcsList}})
GET_FILENAME_COMPONENT(_abs_FILE ${_current_FILE} ABSOLUTE)
GET_FILENAME_COMPONENT(_basename ${_current_FILE} NAME_WE)
SET(_moc ${CMAKE_CURRENT_BINARY_DIR}/${_basename}.moc)
# SET(extra_moc_argument)
# if(WIN32)
# SET(extra_moc_argument -DWIN32)
# endif(WIN32)
QT4_GENERATE_MOC(${_abs_FILE} ${_moc})
# ADD_CUSTOM_COMMAND(OUTPUT ${_moc}
# COMMAND ${QT_MOC_EXECUTABLE}
# ARGS ${extra_moc_argument} ${_moc_INCS} -o ${_moc} ${_abs_FILE}
# DEPENDS ${_current_FILE}
# )
LIST(APPEND ${_srcsList} ${_moc})
ENDFOREACH (_current_FILE)
ENDMACRO(MY_AUTOMOC)
endif()
EXEC_PROGRAM( ${QMAKE_EXECUTABLE} ARGS "-query QT_INSTALL_LIBS" OUTPUT_VARIABLE QT_LIBRARY_DIR )
EXEC_PROGRAM( ${QMAKE_EXECUTABLE} ARGS "-query QT_INSTALL_PREFIX" OUTPUT_VARIABLE QT_PREFIX_DIR )
EXEC_PROGRAM( ${QMAKE_EXECUTABLE} ARGS "-query QT_INSTALL_PLUGINS" OUTPUT_VARIABLE QT_PLUGINS_DIR )
EXEC_PROGRAM( ${QMAKE_EXECUTABLE} ARGS "-query QT_INSTALL_BINS" OUTPUT_VARIABLE QT_BINARY_DIR )
EXEC_PROGRAM( ${QMAKE_EXECUTABLE} ARGS "-query QT_INSTALL_HEADERS" OUTPUT_VARIABLE QT_HEADERS_DIR )
EXEC_PROGRAM( ${QMAKE_EXECUTABLE} ARGS "-query QT_INSTALL_DOCS" OUTPUT_VARIABLE QT_DOC_DIR )
EXEC_PROGRAM( ${QMAKE_EXECUTABLE} ARGS "-query QT_INSTALL_DATA" OUTPUT_VARIABLE QT_DATA_DIR )
EXEC_PROGRAM( ${QMAKE_EXECUTABLE} ARGS "-query QT_HOST_DATA" OUTPUT_VARIABLE QT_ARCHDATA_DIR )
SET( QT_MKSPECS_DIR "${QT_ARCHDATA_DIR}/mkspecs" )
ENDMACRO(SETUP_QT_DIRS)
macro(set_enabled_plugin PLUGIN ENABLED)
# To nice looks
if(ENABLED)
set(ENABLED "on")
else(ENABLED)
else()
set(ENABLED "off")
endif(ENABLED)
endif()
set(WITH_${PLUGIN}_PLUGIN_INTERNAL ${ENABLED} CACHE INTERNAL "")
endmacro(set_enabled_plugin)
@ -72,7 +37,6 @@ endmacro(disable_plugin)
# it used to build examples and tools
macro(target_link_qca_libraries TARGET)
# Link with QCA library
target_link_libraries(${TARGET} ${QT_QTCORE_LIBRARY})
target_link_libraries(${TARGET} ${QCA_LIB_NAME})
# Statically link with all enabled QCA plugins
@ -82,15 +46,19 @@ macro(target_link_qca_libraries TARGET)
# Check plugin for enabled
if(WITH_${PLUGIN}_PLUGIN_INTERNAL)
target_link_libraries(${TARGET} qca-${PLUGIN})
endif(WITH_${PLUGIN}_PLUGIN_INTERNAL)
endif()
endforeach(PLUGIN)
endif(STATIC_PLUGINS)
endif()
endmacro(target_link_qca_libraries)
# it used to build unittests
macro(target_link_qca_test_libraries TARGET)
target_link_qca_libraries(${TARGET})
target_link_libraries(${TARGET} ${QT_QTTEST_LIBRARY})
if(QT6)
target_link_libraries(${TARGET} Qt6::Test)
else()
target_link_libraries(${TARGET} Qt5::Test)
endif()
endmacro(target_link_qca_test_libraries)
# it used to build unittests
@ -109,7 +77,7 @@ macro(install_pdb TARGET INSTALL_PATH)
get_target_property(LOCATION ${TARGET} LOCATION_RELWITHDEBINFO)
string(REGEX REPLACE "\\.[^.]*$" ".pdb" LOCATION "${LOCATION}")
install(FILES ${LOCATION} DESTINATION ${INSTALL_PATH} CONFIGURATIONS RelWithDebInfo)
endif(MSVC)
endif()
endmacro(install_pdb)
macro(normalize_path PATH)

View File

@ -4,7 +4,7 @@ cmake_policy(SET CMP0007 OLD)
if (NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
message(FATAL_ERROR "Cannot find install manifest: \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\"")
endif(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
endif()
file(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files)
string(REGEX REPLACE "\n" ";" files "${files}")
@ -19,8 +19,8 @@ foreach (file ${files})
)
if(NOT ${rm_retval} EQUAL 0)
message(FATAL_ERROR "Problem when removing \"$ENV{DESTDIR}${file}\"")
endif (NOT ${rm_retval} EQUAL 0)
else (EXISTS "$ENV{DESTDIR}${file}")
endif()
else()
message(STATUS "File \"$ENV{DESTDIR}${file}\" does not exist.")
endif (EXISTS "$ENV{DESTDIR}${file}")
endif()
endforeach(file)

View File

@ -5,11 +5,11 @@ CONFIG *= qt
LINKAGE =
exists($$QCA_LIBDIR/qca.framework) {
exists($$QCA_LIBDIR/@QCA_LIB_NAME@.framework) {
QMAKE_CXXFLAGS += -F$$QCA_LIBDIR
LIBS *= -F$$QCA_LIBDIR
INCLUDEPATH += $$QCA_LIBDIR/qca.framework/Headers
LINKAGE = -framework qca
INCLUDEPATH += $$QCA_LIBDIR/@QCA_LIB_NAME@.framework/Headers
LINKAGE = -framework @QCA_LIB_NAME@
}
# else, link normally

3
docs/Doxyfile.local Normal file
View File

@ -0,0 +1,3 @@
### KApiDox Project-specific Overrides File
FILE_PATTERNS += *.doco

View File

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

View File

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

@ -1,5 +1,8 @@
if(Qt5Core_FOUND)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Qt5Core_EXECUTABLE_COMPILE_FLAGS}")
if(QT6)
find_package(Qt6 REQUIRED Network)
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Qt5Core_EXECUTABLE_COMPILE_FLAGS}")
find_package(Qt5 REQUIRED Network)
endif()
add_subdirectory(aes-cmac)
add_subdirectory(base64test)

View File

@ -31,156 +31,144 @@
class AESCMACContext : public QCA::MACContext
{
Q_OBJECT
public:
AESCMACContext(QCA::Provider *p) : QCA::MACContext(p, "cmac(aes)")
AESCMACContext(QCA::Provider *p)
: QCA::MACContext(p, QStringLiteral("cmac(aes)"))
{
}
~AESCMACContext()
{
}
// Helper to left shift an arbitrary length array
// This is heavily based on the example in the I-D.
QCA::SecureArray leftShift(const QCA::SecureArray &array)
{
// We create an output of the same size as the input
QCA::SecureArray out(array.size());
// We handle one byte at a time - this is the high bit
// from the previous byte.
int overflow = 0;
// We create an output of the same size as the input
QCA::SecureArray out(array.size());
// We handle one byte at a time - this is the high bit
// from the previous byte.
int overflow = 0;
// work through each byte.
for (int i = array.size() -1; i >= 0; --i) {
// do the left shift on this byte.
out[i] = array[i] << 1;
// make the low bit on this byte be the high bit
// from the previous byte.
out[i] |= overflow;
// save the high bit for next time
overflow = (array[i] & 0x80) ? 1 : 0;
}
return out;
// work through each byte.
for (int i = array.size() - 1; i >= 0; --i) {
// do the left shift on this byte.
out[i] = array[i] << 1;
// make the low bit on this byte be the high bit
// from the previous byte.
out[i] |= overflow;
// save the high bit for next time
overflow = (array[i] & 0x80) ? 1 : 0;
}
return out;
}
// Helper to XOR two arrays - must be same length
QCA::SecureArray xorArray(const QCA::SecureArray &array1,
const QCA::SecureArray &array2)
QCA::SecureArray xorArray(const QCA::SecureArray &array1, const QCA::SecureArray &array2)
{
if (array1.size() != array2.size())
// empty array
return QCA::SecureArray();
if (array1.size() != array2.size())
// empty array
return QCA::SecureArray();
QCA::SecureArray result(array1.size());
QCA::SecureArray result(array1.size());
for (int i = 0; i < array1.size(); ++i)
result[i] = array1[i] ^ array2[i];
for (int i = 0; i < array1.size(); ++i)
result[i] = array1[i] ^ array2[i];
return result;
return result;
}
void setup(const QCA::SymmetricKey &key)
void setup(const QCA::SymmetricKey &key) override
{
// We might not have a real key, since this can get called
// from the constructor.
if (key.size() == 0)
return;
// We might not have a real key, since this can get called
// from the constructor.
if (key.size() == 0)
return;
m_key = key;
// Generate the subkeys
QCA::SecureArray const_Zero(16);
QCA::SecureArray const_Rb(16);
const_Rb[15] = (char)0x87;
m_key = key;
// Generate the subkeys
QCA::SecureArray const_Zero(16);
QCA::SecureArray const_Rb(16);
const_Rb[15] = (char)0x87;
m_X = const_Zero;
m_residual = QCA::SecureArray();
m_X = const_Zero;
m_residual = QCA::SecureArray();
// Figure 2.2, step 1.
QCA::Cipher aesObj(QString("aes128"),
QCA::Cipher::ECB, QCA::Cipher::DefaultPadding,
QCA::Encode, key);
QCA::SecureArray L = aesObj.process(const_Zero);
// Figure 2.2, step 1.
QCA::Cipher aesObj(QStringLiteral("aes128"), QCA::Cipher::ECB, QCA::Cipher::DefaultPadding, QCA::Encode, key);
QCA::SecureArray L = aesObj.process(const_Zero);
// Figure 2.2, step 2
if (0 == (L[0] & 0x80))
m_k1 = leftShift(L);
else
m_k1 = xorArray(leftShift(L), const_Rb);
// Figure 2.2, step 2
if (0 == (L[0] & 0x80))
m_k1 = leftShift(L);
else
m_k1 = xorArray(leftShift(L), const_Rb);
// Figure 2.2, step 3
if (0 == (m_k1[0] & 0x80))
m_k2 = leftShift(m_k1);
else
m_k2 = xorArray(leftShift(m_k1), const_Rb);
// Figure 2.2, step 3
if (0 == (m_k1[0] & 0x80))
m_k2 = leftShift(m_k1);
else
m_k2 = xorArray(leftShift(m_k1), const_Rb);
}
QCA::Provider::Context *clone() const
QCA::Provider::Context *clone() const override
{
return new AESCMACContext(*this);
}
void clear()
{
setup(m_key);
setup(m_key);
}
QCA::KeyLength keyLength() const
QCA::KeyLength keyLength() const override
{
return QCA::KeyLength(16, 16, 1);
}
// This is a bit different to the way the I-D does it,
// to allow for multiple update() calls.
void update(const QCA::MemoryRegion &a)
void update(const QCA::MemoryRegion &a) override
{
QCA::SecureArray bytesToProcess = m_residual + a;
int blockNum;
// note that we don't want to do the last full block here, because
// it needs special treatment in final().
for (blockNum = 0; blockNum < ((bytesToProcess.size()-1)/16); ++blockNum) {
// copy a block of data
QCA::SecureArray thisBlock(16);
for (int yalv = 0; yalv < 16; ++yalv)
thisBlock[yalv] = bytesToProcess[blockNum*16 + yalv];
QCA::SecureArray bytesToProcess = m_residual + a;
int blockNum;
// note that we don't want to do the last full block here, because
// it needs special treatment in final().
for (blockNum = 0; blockNum < ((bytesToProcess.size() - 1) / 16); ++blockNum) {
// copy a block of data
QCA::SecureArray thisBlock(16);
for (int yalv = 0; yalv < 16; ++yalv)
thisBlock[yalv] = bytesToProcess[blockNum * 16 + yalv];
m_Y = xorArray(m_X, thisBlock);
m_Y = xorArray(m_X, thisBlock);
QCA::Cipher aesObj(QString("aes128"),
QCA::Cipher::ECB, QCA::Cipher::DefaultPadding,
QCA::Encode, m_key);
m_X = aesObj.process(m_Y);
}
// This can be between 1 and 16
int numBytesLeft = bytesToProcess.size() - 16*blockNum;
// we copy the left over part
m_residual.resize(numBytesLeft);
for(int yalv = 0; yalv < numBytesLeft; ++yalv)
m_residual[yalv] = bytesToProcess[blockNum*16 + yalv];
QCA::Cipher aesObj(
QStringLiteral("aes128"), QCA::Cipher::ECB, QCA::Cipher::DefaultPadding, QCA::Encode, m_key);
m_X = aesObj.process(m_Y);
}
// This can be between 1 and 16
int numBytesLeft = bytesToProcess.size() - 16 * blockNum;
// we copy the left over part
m_residual.resize(numBytesLeft);
for (int yalv = 0; yalv < numBytesLeft; ++yalv)
m_residual[yalv] = bytesToProcess[blockNum * 16 + yalv];
}
void final( QCA::MemoryRegion *out)
void final(QCA::MemoryRegion *out) override
{
QCA::SecureArray lastBlock;
int numBytesLeft = m_residual.size();
if ( numBytesLeft != 16 ) {
// no full block, so we have to pad.
m_residual.resize(16);
m_residual[numBytesLeft] = (char)0x80;
lastBlock = xorArray(m_residual, m_k2);
} else {
// this is a full block - no padding
lastBlock = xorArray(m_residual, m_k1);
}
m_Y = xorArray(m_X, lastBlock);
QCA::Cipher aesObj(QString("aes128"),
QCA::Cipher::ECB, QCA::Cipher::DefaultPadding,
QCA::Encode, m_key);
*out = aesObj.process(m_Y);
QCA::SecureArray lastBlock;
int numBytesLeft = m_residual.size();
if (numBytesLeft != 16) {
// no full block, so we have to pad.
m_residual.resize(16);
m_residual[numBytesLeft] = (char)0x80;
lastBlock = xorArray(m_residual, m_k2);
} else {
// this is a full block - no padding
lastBlock = xorArray(m_residual, m_k1);
}
m_Y = xorArray(m_X, lastBlock);
QCA::Cipher aesObj(QStringLiteral("aes128"), QCA::Cipher::ECB, QCA::Cipher::DefaultPadding, QCA::Encode, m_key);
*out = aesObj.process(m_Y);
}
protected:
@ -202,49 +190,47 @@ protected:
class ClientSideProvider : public QCA::Provider
{
public:
int qcaVersion() const
{
return QCA_VERSION;
}
int qcaVersion() const override
{
return QCA_VERSION;
}
QString name() const
{
return "exampleClientSideProvider";
}
QString name() const override
{
return QStringLiteral("exampleClientSideProvider");
}
QStringList features() const
{
QStringList list;
list += "cmac(aes)";
// you can add more features in here, if you have some.
return list;
}
QStringList features() const override
{
QStringList list;
list += QStringLiteral("cmac(aes)");
// you can add more features in here, if you have some.
return list;
}
Provider::Context *createContext(const QString &type)
{
if(type == "cmac(aes)")
return new AESCMACContext(this);
// else if (type == some other feature)
// return some other context.
else
return 0;
}
Provider::Context *createContext(const QString &type) override
{
if (type == QLatin1String("cmac(aes)"))
return new AESCMACContext(this);
// else if (type == some other feature)
// return some other context.
else
return nullptr;
}
};
// AES CMAC is a Message Authentication Code based on a block cipher
// instead of the more normal keyed hash.
// See RFC 4493 "The AES-CMAC Algorithm"
class AES_CMAC: public QCA::MessageAuthenticationCode
class AES_CMAC : public QCA::MessageAuthenticationCode
{
public:
AES_CMAC(const QCA::SymmetricKey &key = QCA::SymmetricKey(),
const QString &provider = QString()):
QCA::MessageAuthenticationCode( "cmac(aes)", key, provider)
{}
AES_CMAC(const QCA::SymmetricKey &key = QCA::SymmetricKey(), const QString &provider = QString())
: QCA::MessageAuthenticationCode(QStringLiteral("cmac(aes)"), key, provider)
{
}
};
int main(int argc, char **argv)
{
// the Initializer object sets things up, and
@ -255,64 +241,66 @@ int main(int argc, char **argv)
QCoreApplication app(argc, argv);
if( ! QCA::isSupported("aes128-ecb") ) {
qDebug() << "AES not supported!";
if (!QCA::isSupported("aes128-ecb")) {
qDebug() << "AES not supported!";
}
if ( QCA::insertProvider(new ClientSideProvider, 0) )
qDebug() << "Inserted our provider";
if (QCA::insertProvider(new ClientSideProvider, 0))
qDebug() << "Inserted our provider";
else
qDebug() << "our provider could not be added";
qDebug() << "our provider could not be added";
// We should check AES CMAC is supported before using it.
if( ! QCA::isSupported("cmac(aes)") ) {
qDebug() << "AES CMAC not supported!";
if (!QCA::isSupported("cmac(aes)")) {
qDebug() << "AES CMAC not supported!";
} else {
// create the required object
AES_CMAC cmacObject;
// create the required object
AES_CMAC cmacObject;
// create the key
QCA::SymmetricKey key(QCA::hexToArray("2b7e151628aed2a6abf7158809cf4f3c"));
// create the key
QCA::SymmetricKey key(QCA::hexToArray(QStringLiteral("2b7e151628aed2a6abf7158809cf4f3c")));
// set the MAC to use the key
cmacObject.setup(key);
// set the MAC to use the key
cmacObject.setup(key);
QCA::SecureArray message = QCA::hexToArray("6bc1bee22e409f96e93d7e117393172a"
"ae2d8a571e03ac9c9eb76fac45af8e51"
"30c81c46a35ce411e5fbc1191a0a52ef"
"f69f2445df4f9b17ad2b417be66c3710");
QCA::SecureArray message1(message);
message1.resize(0);
qDebug();
qDebug() << "Message1: " << QCA::arrayToHex(message1.toByteArray());
qDebug() << "Expecting: bb1d6929e95937287fa37d129b756746";
qDebug() << "AES-CMAC: " << QCA::arrayToHex(cmacObject.process(message1).toByteArray());
QCA::SecureArray message =
QCA::hexToArray(QStringLiteral("6bc1bee22e409f96e93d7e117393172a"
"ae2d8a571e03ac9c9eb76fac45af8e51"
"30c81c46a35ce411e5fbc1191a0a52ef"
"f69f2445df4f9b17ad2b417be66c3710"));
QCA::SecureArray message1(message);
message1.resize(0);
qDebug();
qDebug() << "Message1: " << QCA::arrayToHex(message1.toByteArray());
qDebug() << "Expecting: bb1d6929e95937287fa37d129b756746";
qDebug() << "AES-CMAC: " << QCA::arrayToHex(cmacObject.process(message1).toByteArray());
cmacObject.clear();
QCA::SecureArray message2(message);
message2.resize(16);
qDebug();
qDebug() << "Message2: " << QCA::arrayToHex(message2.toByteArray());
qDebug() << "Expecting: 070a16b46b4d4144f79bdd9dd04a287c";
qDebug() << "AES-CMAC: " << QCA::arrayToHex(cmacObject.process(message2).toByteArray());
cmacObject.clear();
QCA::SecureArray message2(message);
message2.resize(16);
qDebug();
qDebug() << "Message2: " << QCA::arrayToHex(message2.toByteArray());
qDebug() << "Expecting: 070a16b46b4d4144f79bdd9dd04a287c";
qDebug() << "AES-CMAC: " << QCA::arrayToHex(cmacObject.process(message2).toByteArray());
cmacObject.clear();
QCA::SecureArray message3(message);
message3.resize(40);
qDebug();
qDebug() << "Message3: " << QCA::arrayToHex(message3.toByteArray());
qDebug() << "Expecting: dfa66747de9ae63030ca32611497c827";
qDebug() << "AES-CMAC " << QCA::arrayToHex(cmacObject.process(message3).toByteArray());
cmacObject.clear();
QCA::SecureArray message3(message);
message3.resize(40);
qDebug();
qDebug() << "Message3: " << QCA::arrayToHex(message3.toByteArray());
qDebug() << "Expecting: dfa66747de9ae63030ca32611497c827";
qDebug() << "AES-CMAC " << QCA::arrayToHex(cmacObject.process(message3).toByteArray());
cmacObject.clear();
QCA::SecureArray message4(message);
message4.resize(64);
qDebug();
qDebug() << "Message4: " << QCA::arrayToHex(message4.toByteArray());
qDebug() << "Expecting: 51f0bebf7e3b9d92fc49741779363cfe";
qDebug() << "AES-CMAC: " << QCA::arrayToHex(cmacObject.process(message4).toByteArray());
cmacObject.clear();
QCA::SecureArray message4(message);
message4.resize(64);
qDebug();
qDebug() << "Message4: " << QCA::arrayToHex(message4.toByteArray());
qDebug() << "Expecting: 51f0bebf7e3b9d92fc49741779363cfe";
qDebug() << "AES-CMAC: " << QCA::arrayToHex(cmacObject.process(message4).toByteArray());
}
return 0;
}
#include "aes-cmac.moc"

View File

@ -32,40 +32,39 @@
int main(int argc, char **argv)
{
QCoreApplication(argc, argv);
QCoreApplication(argc, argv);
// the Initializer object sets things up, and
// also does cleanup when it goes out of scope
QCA::Initializer init;
// the Initializer object sets things up, and
// also does cleanup when it goes out of scope
QCA::Initializer init;
// we use the first argument as the data to encode
// if an argument is provided. Use "hello" if no argument
QByteArray arg; // empty array
arg.append((argc >= 2) ? argv[1] : "hello");
// we use the first argument as the data to encode
// if an argument is provided. Use "hello" if no argument
QByteArray arg; // empty array
arg.append((argc >= 2) ? argv[1] : "hello");
// create our object, which does encoding by default
// QCA::Base64 encoder(QCA::Encode); is equivalent
QCA::Base64 encoder;
// create our object, which does encoding by default
// QCA::Base64 encoder(QCA::Encode); is equivalent
QCA::Base64 encoder;
// This does the actual conversion (encoding).
// You might prefer to use encoder.encode(); and have
// it return a QCA::SecureArray, depending on your needs
QString encoded = encoder.arrayToString(arg);
// This does the actual conversion (encoding).
// You might prefer to use encoder.encode(); and have
// it return a QCA::SecureArray, depending on your needs
QString encoded = encoder.arrayToString(arg);
std::cout << arg.data() << " in base64 encoding is ";
std::cout << encoded.toLatin1().data() << std::endl;
std::cout << arg.data() << " in base64 encoding is ";
std::cout << encoded.toLatin1().data() << std::endl;
// This time, we'll create an object to decode base64. We
// could also have reused the existing object, calling
// clear(); and setup(QCA::Decode); on it.
QCA::Base64 decoder(QCA::Decode);
// This time, we'll create an object to decode base64. We
// could also have reused the existing object, calling
// clear(); and setup(QCA::Decode); on it.
QCA::Base64 decoder(QCA::Decode);
// This time, we convert a QString into a QString
QString decoded = decoder.decodeString(encoded);
// This time, we convert a QString into a QString
QString decoded = decoder.decodeString(encoded);
std::cout << encoded.toLatin1().data() << " decoded from base64 is ";
std::cout << decoded.toLatin1().data() << std::endl;
std::cout << encoded.toLatin1().data() << " decoded from base64 is ";
std::cout << decoded.toLatin1().data() << std::endl;
return 0;
return 0;
}

View File

@ -20,10 +20,10 @@
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <QtCrypto>
#include <QCoreApplication>
#include <QFile>
#include <iostream>
@ -34,7 +34,7 @@
// dump out information about some part of the certificate
// we use this same approach for information about the subject
// of the certificate, and also about the issuer of the certificate
static void dumpCertificateInfo( QCA::CertificateInfo info)
static void dumpCertificateInfo(const QCA::CertificateInfo &info)
{
std::cout << " Organization: " << std::endl;
@ -48,37 +48,35 @@ static void dumpCertificateInfo( QCA::CertificateInfo info)
// out each value. Note that is uncommon for a certificate to
// actually contain multiple values for a single parameter.
QString organization;
foreach( organization, orgInfoList ) {
std::cout << " " << qPrintable(organization) << std::endl;
foreach (organization, orgInfoList) {
std::cout << " " << qPrintable(organization) << std::endl;
}
std::cout << " Country: " << std::endl;
// As above, however this shows a more compact way to represent
// the iteration and output.
foreach( QString country, info.values(QCA::Country) ) {
std::cout << " " << qPrintable(country) << std::endl;
foreach (QString country, info.values(QCA::Country)) { // clazy:exclude=container-anti-pattern
std::cout << " " << qPrintable(country) << std::endl;
}
}
// This is just a convenience routine
static void dumpSubjectInfo( QCA::CertificateInfo subject)
static void dumpSubjectInfo(const QCA::CertificateInfo &subject)
{
std::cout << "Subject: " << std::endl;
dumpCertificateInfo( subject );
dumpCertificateInfo(subject);
}
// This is just a convenience routine
static void dumpIssuerInfo( QCA::CertificateInfo issuer)
static void dumpIssuerInfo(const QCA::CertificateInfo &issuer)
{
std::cout << "Issuer: " << std::endl;
dumpCertificateInfo( issuer );
dumpCertificateInfo(issuer);
}
int main(int argc, char** argv)
int main(int argc, char **argv)
{
// the Initializer object sets things up, and
// also does cleanup when it goes out of scope
@ -87,9 +85,9 @@ int main(int argc, char** argv)
QCoreApplication app(argc, argv);
// We need to ensure that we have certificate handling support
if ( !QCA::isSupported( "cert" ) ) {
std::cout << "Sorry, no PKI certificate support" << std::endl;
return 1;
if (!QCA::isSupported("cert")) {
std::cout << "Sorry, no PKI certificate support" << std::endl;
return 1;
}
// We are going to work with a number of certificates, and a
@ -100,77 +98,76 @@ int main(int argc, char** argv)
// as a filename to read the keys from. If there is no argument, we just
// read from the system store certificates.
if (argc >= 2) {
// we are going to read the certificates in using a single call
// which requires a CertificateCollection.
QCA::CertificateCollection filecerts;
// The conversion can be tested (although you don't have to) to find out if it
// worked.
QCA::ConvertResult importResult;
// This imports all the PEM encoded certificates from the file specified as the argument
// Note that you pass in a pointer to the result argument.
filecerts = QCA::CertificateCollection::fromFlatTextFile( argv[1], &importResult );
if ( QCA::ConvertGood == importResult) {
std::cout << "Import succeeded" << std::endl;
// this turns the CertificateCollection into a QList of Certificate objects
certlist = filecerts.certificates();
}
// we are going to read the certificates in using a single call
// which requires a CertificateCollection.
QCA::CertificateCollection filecerts;
// The conversion can be tested (although you don't have to) to find out if it
// worked.
QCA::ConvertResult importResult;
// This imports all the PEM encoded certificates from the file specified as the argument
// Note that you pass in a pointer to the result argument.
filecerts = QCA::CertificateCollection::fromFlatTextFile(QFile::decodeName(argv[1]), &importResult);
if (QCA::ConvertGood == importResult) {
std::cout << "Import succeeded" << std::endl;
// this turns the CertificateCollection into a QList of Certificate objects
certlist = filecerts.certificates();
}
} else {
// we have no arguments, so just use the system certificates
if ( !QCA::haveSystemStore() ) {
std::cout << "System certificates not available" << std::endl;
return 2;
}
// we have no arguments, so just use the system certificates
if (!QCA::haveSystemStore()) {
std::cout << "System certificates not available" << std::endl;
return 2;
}
// Similar to above, except we just want the system certificates
QCA::CertificateCollection systemcerts = QCA::systemStore();
// Similar to above, except we just want the system certificates
QCA::CertificateCollection systemcerts = QCA::systemStore();
// this turns the CertificateCollection into a QList of Certificate objects
certlist = systemcerts.certificates();
// this turns the CertificateCollection into a QList of Certificate objects
certlist = systemcerts.certificates();
}
std::cout << "Number of certificates: " << certlist.count() << std::endl;
QCA::Certificate cert;
foreach (cert, certlist) {
std::cout << "Serial Number:";
// the serial number of the certificate is a QCA::BigInteger, but we can
// just convert it to a string, and then output it.
std::cout << qPrintable(cert.serialNumber().toString()) << std::endl;
std::cout << "Serial Number:";
// the serial number of the certificate is a QCA::BigInteger, but we can
// just convert it to a string, and then output it.
std::cout << qPrintable(cert.serialNumber().toString()) << std::endl;
// The subject information shows properties of who the certificate
// applies to. See the convenience routines above.
dumpSubjectInfo( cert.subjectInfo() );
// The subject information shows properties of who the certificate
// applies to. See the convenience routines above.
dumpSubjectInfo(cert.subjectInfo());
// The issuer information shows properties of who the certificate
// was signed by. See the convenience routines above.
dumpIssuerInfo( cert.issuerInfo() );
// The issuer information shows properties of who the certificate
// was signed by. See the convenience routines above.
dumpIssuerInfo(cert.issuerInfo());
// Test if the certificate can be used as a certificate authority
if ( cert.isCA() ) {
std::cout << "Is certificate authority" << std::endl;
} else {
std::cout << "Is not a certificate authority" << std::endl;
}
// Test if the certificate can be used as a certificate authority
if (cert.isCA()) {
std::cout << "Is certificate authority" << std::endl;
} else {
std::cout << "Is not a certificate authority" << std::endl;
}
// Test if the certificate is self-signed.
if (cert.isSelfSigned() ) {
std::cout << "Self signed" << std::endl;
} else {
std::cout << "Is not self-signed!!!" << std::endl;
}
// Test if the certificate is self-signed.
if (cert.isSelfSigned()) {
std::cout << "Self signed" << std::endl;
} else {
std::cout << "Is not self-signed!!!" << std::endl;
}
// Certificate are only valid between specific dates. We can get the dates
// (as a QDateTime) using a couple of calls
std::cout << "Valid from " << qPrintable(cert.notValidBefore().toString());
std::cout << ", until " << qPrintable(cert.notValidAfter().toString());
std::cout << std::endl;
// Certificate are only valid between specific dates. We can get the dates
// (as a QDateTime) using a couple of calls
std::cout << "Valid from " << qPrintable(cert.notValidBefore().toString());
std::cout << ", until " << qPrintable(cert.notValidAfter().toString());
std::cout << std::endl;
// You can get the certificate in PEM encoding with a simple toPEM() call
std::cout << "PEM:" << std::endl;
std::cout << qPrintable(cert.toPEM());
std::cout << std::endl << std::endl;
}
// You can get the certificate in PEM encoding with a simple toPEM() call
std::cout << "PEM:" << std::endl;
std::cout << qPrintable(cert.toPEM());
std::cout << std::endl << std::endl;
}
return 0;
}

View File

@ -22,7 +22,7 @@
// QtCrypto has the declarations for all of QCA
#include <QtCrypto>
#include <stdio.h>
#include <cstdio>
#include <QCoreApplication>
@ -43,91 +43,88 @@ int main(int argc, char **argv)
QCA::SecureArray arg = (argc >= 2) ? argv[1] : "hello";
// AES128 testing
if(!QCA::isSupported("aes128-cbc-pkcs7"))
printf("AES128-CBC not supported!\n");
if (!QCA::isSupported("aes128-cbc-pkcs7"))
printf("AES128-CBC not supported!\n");
else {
// Create a random key - you'd probably use one from another
// source in a real application
QCA::SymmetricKey key(16);
// Create a random key - you'd probably use one from another
// source in a real application
QCA::SymmetricKey key(16);
// Create a random initialisation vector - you need this
// value to decrypt the resulting cipher text, but it
// need not be kept secret (unlike the key).
QCA::InitializationVector iv(16);
// Create a random initialisation vector - you need this
// value to decrypt the resulting cipher text, but it
// need not be kept secret (unlike the key).
QCA::InitializationVector iv(16);
// create a 128 bit AES cipher object using Cipher Block Chaining (CBC) mode
QCA::Cipher cipher(QString("aes128"),QCA::Cipher::CBC,
// use Default padding, which is equivalent to PKCS7 for CBC
QCA::Cipher::DefaultPadding,
// this object will encrypt
QCA::Encode,
key, iv);
// create a 128 bit AES cipher object using Cipher Block Chaining (CBC) mode
QCA::Cipher cipher(QStringLiteral("aes128"),
QCA::Cipher::CBC,
// use Default padding, which is equivalent to PKCS7 for CBC
QCA::Cipher::DefaultPadding,
// this object will encrypt
QCA::Encode,
key,
iv);
// we use the cipher object to encrypt the argument we passed in
// the result of that is returned - note that if there is less than
// 16 bytes (1 block), then nothing will be returned - it is buffered
// update() can be called as many times as required.
QCA::SecureArray u = cipher.update(arg);
// we use the cipher object to encrypt the argument we passed in
// the result of that is returned - note that if there is less than
// 16 bytes (1 block), then nothing will be returned - it is buffered
// update() can be called as many times as required.
QCA::SecureArray u = cipher.update(arg);
// We need to check if that update() call worked.
if (!cipher.ok()) {
printf("Update failed\n");
}
// output the results of that stage
printf("AES128 encryption of %s is [%s]\n",
arg.data(),
qPrintable(QCA::arrayToHex(u.toByteArray())) );
// We need to check if that update() call worked.
if (!cipher.ok()) {
printf("Update failed\n");
}
// output the results of that stage
printf("AES128 encryption of %s is [%s]\n", arg.data(), qPrintable(QCA::arrayToHex(u.toByteArray())));
// Because we are using PKCS7 padding, we need to output the final (padded) block
// Note that we should always call final() even with no padding, to clean up
QCA::SecureArray f = cipher.final();
// Because we are using PKCS7 padding, we need to output the final (padded) block
// Note that we should always call final() even with no padding, to clean up
QCA::SecureArray f = cipher.final();
// Check if the final() call worked
if (!cipher.ok()) {
printf("Final failed\n");
}
// and output the resulting block. The ciphertext is the results of update()
// and the result of final()
printf("Final block for AES128 encryption is [0x%s]\n", qPrintable(QCA::arrayToHex(f.toByteArray())));
// Check if the final() call worked
if (!cipher.ok()) {
printf("Final failed\n");
}
// and output the resulting block. The ciphertext is the results of update()
// and the result of final()
printf("Final block for AES128 encryption is [0x%s]\n", qPrintable(QCA::arrayToHex(f.toByteArray())) );
// re-use the Cipher t decrypt. We need to use the same key and
// initialisation vector as in the encryption.
cipher.setup(QCA::Decode, key, iv);
// re-use the Cipher t decrypt. We need to use the same key and
// initialisation vector as in the encryption.
cipher.setup( QCA::Decode, key, iv );
// Build a single cipher text array. You could also call update() with
// each block as you receive it, if that is more useful.
QCA::SecureArray cipherText = u.append(f);
// Build a single cipher text array. You could also call update() with
// each block as you receive it, if that is more useful.
QCA::SecureArray cipherText = u.append(f);
// take that cipher text, and decrypt it
QCA::SecureArray plainText = cipher.update(cipherText);
// take that cipher text, and decrypt it
QCA::SecureArray plainText = cipher.update(cipherText);
// check if the update() call worked
if (!cipher.ok()) {
printf("Update failed\n");
}
// check if the update() call worked
if (!cipher.ok()) {
printf("Update failed\n");
}
// output results
printf("Decryption using AES128 of [0x%s] is %s\n",
qPrintable(QCA::arrayToHex(cipherText.toByteArray())),
plainText.data());
// output results
printf("Decryption using AES128 of [0x%s] is %s\n",
qPrintable(QCA::arrayToHex(cipherText.toByteArray())), plainText.data());
// Again we need to call final(), to get the last block (with its padding removed)
plainText = cipher.final();
// Again we need to call final(), to get the last block (with its padding removed)
plainText = cipher.final();
// check if the final() call worked
if (!cipher.ok()) {
printf("Final failed\n");
}
// output results
printf("Final decryption block using AES128 is %s\n", plainText.data());
// instead of update() and final(), you can do the whole thing
// in one step, using process()
printf("One step decryption using AES128: %s\n",
QCA::SecureArray(cipher.process(cipherText)).data() );
// check if the final() call worked
if (!cipher.ok()) {
printf("Final failed\n");
}
// output results
printf("Final decryption block using AES128 is %s\n", plainText.data());
// instead of update() and final(), you can do the whole thing
// in one step, using process()
printf("One step decryption using AES128: %s\n", QCA::SecureArray(cipher.process(cipherText)).data());
}
return 0;
}

View File

@ -20,7 +20,6 @@
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <QtCrypto>
#include <QCoreApplication>
@ -30,7 +29,7 @@
#include "import_plugins.h"
#endif
int main(int argc, char** argv)
int main(int argc, char **argv)
{
// the Initializer object sets things up, and
// also does cleanup when it goes out of scope
@ -39,31 +38,31 @@ int main(int argc, char** argv)
QCoreApplication app(argc, argv);
// We need to ensure that we have certificate handling support
if ( !QCA::isSupported( "cert" ) ) {
qWarning() << "Sorry, no PKI certificate support";
return 1;
if (!QCA::isSupported("cert")) {
qWarning() << "Sorry, no PKI certificate support";
return 1;
}
// Read in a public key cert
// you could also build this using the fromPEMFile() method
QCA::Certificate pubCert( "User.pem" );
if ( pubCert.isNull() ) {
qWarning() << "Sorry, could not import public key certificate";
return 1;
QCA::Certificate pubCert(QStringLiteral("User.pem"));
if (pubCert.isNull()) {
qWarning() << "Sorry, could not import public key certificate";
return 1;
}
// We are building the certificate into a SecureMessageKey object, via a
// CertificateChain
QCA::SecureMessageKey secMsgKey;
QCA::CertificateChain chain;
chain += pubCert;
secMsgKey.setX509CertificateChain( chain );
secMsgKey.setX509CertificateChain(chain);
// build up a SecureMessage object, based on our public key certificate
if ( !QCA::isSupported( "cms" ) ) {
qWarning() << "Sorry, no CMS support";
return 1;
if (!QCA::isSupported("cms")) {
qWarning() << "Sorry, no CMS support";
return 1;
}
QCA::CMS cms;
QCA::CMS cms;
QCA::SecureMessage msg(&cms);
msg.setRecipient(secMsgKey);
@ -78,35 +77,34 @@ int main(int argc, char** argv)
msg.waitForFinished(1000);
// check to see if it worked
if(!msg.success())
{
qWarning() << "Error encrypting: " << msg.errorCode();
return 1;
if (!msg.success()) {
qWarning() << "Error encrypting: " << msg.errorCode();
return 1;
}
// get the result
QByteArray cipherText = msg.read();
QByteArray cipherText = msg.read();
QCA::Base64 enc;
qDebug() << "'" << plainText.data() << "' encrypts to (in base 64): ";
qDebug() << enc.arrayToString( cipherText );
qDebug() << enc.arrayToString(cipherText);
qDebug() << "Message uses" << msg.hashName() << "hashing algorithm";
qDebug();
// Show we can decrypt it with the private key
// Read in a private key
QCA::PrivateKey privKey;
QCA::PrivateKey privKey;
QCA::ConvertResult convRes;
QCA::SecureArray passPhrase = "start";
privKey = QCA::PrivateKey::fromPEMFile( "Userkey.pem", passPhrase, &convRes );
if ( convRes != QCA::ConvertGood ) {
qWarning() << "Sorry, could not import Private Key";
return 1;
QCA::SecureArray passPhrase = "start";
privKey = QCA::PrivateKey::fromPEMFile(QStringLiteral("Userkey.pem"), passPhrase, &convRes);
if (convRes != QCA::ConvertGood) {
qWarning() << "Sorry, could not import Private Key";
return 1;
}
QCA::SecureMessageKey secMsgKey2;
// needed?
secMsgKey2.setX509CertificateChain( chain );
secMsgKey2.setX509CertificateChain(chain);
secMsgKey2.setX509PrivateKey(privKey);
QCA::SecureMessageKeyList privKeyList;
privKeyList += secMsgKey2;
@ -116,35 +114,31 @@ int main(int argc, char** argv)
// this example simulates encryption and one end, and decryption
// at the other
QCA::CMS anotherCms;
anotherCms.setPrivateKeys( privKeyList );
anotherCms.setPrivateKeys(privKeyList);
QCA::SecureMessage msg2( &anotherCms );
QCA::SecureMessage msg2(&anotherCms);
msg2.startDecrypt();
msg2.update( cipherText );
msg2.update(cipherText);
msg2.end();
// I think it is reasonable to wait for 1 second for this
msg2.waitForFinished(1000);
// check to see if it worked
if(!msg2.success())
{
qWarning() << "Error encrypting: " << msg2.errorCode();
return 1;
if (!msg2.success()) {
qWarning() << "Error encrypting: " << msg2.errorCode();
return 1;
}
QCA::SecureArray plainTextResult = msg2.read();
qDebug() << enc.arrayToString( cipherText )
<< " (in base 64) decrypts to: "
<< plainTextResult.data();
qDebug() << enc.arrayToString(cipherText) << " (in base 64) decrypts to: " << plainTextResult.data();
if (msg2.wasSigned()) {
qDebug() << "Message was signed at "
<< msg2.signer().timestamp();
qDebug() << "Message was signed at " << msg2.signer().timestamp();
} else {
qDebug() << "Message was not signed";
qDebug() << "Message was not signed";
}
qDebug() << "Message used" << msg2.hashName() << "hashing algorithm";
@ -155,7 +149,7 @@ int main(int argc, char** argv)
QByteArray text("Got your message");
// Re-use the CMS and SecureMessageKeyList objects from the decrypt...
QCA::SecureMessage signing( &anotherCms );
QCA::SecureMessage signing(&anotherCms);
signing.setSigners(privKeyList);
signing.startSign(QCA::SecureMessage::Detached);
@ -166,23 +160,21 @@ int main(int argc, char** argv)
signing.waitForFinished(1000);
// check to see if it worked
if(!signing.success())
{
qWarning() << "Error signing: " << signing.errorCode();
return 1;
if (!signing.success()) {
qWarning() << "Error signing: " << signing.errorCode();
return 1;
}
// get the result
QByteArray signature = signing.signature();
qDebug() << "'" << text.data() << "', signature (converted to base 64), is: ";
qDebug() << enc.arrayToString( signature );
qDebug() << enc.arrayToString(signature);
qDebug() << "Message uses" << signing.hashName() << "hashing algorithm";
qDebug();
// Now we go back to the first CMS, and re-use that.
QCA::SecureMessage verifying( &cms );
QCA::SecureMessage verifying(&cms);
// You have to pass the signature to startVerify(),
// and the message to update()
@ -193,23 +185,20 @@ int main(int argc, char** argv)
verifying.waitForFinished(1000);
// check to see if it worked
if(!verifying.success())
{
qWarning() << "Error verifying: " << verifying.errorCode();
return 1;
if (!verifying.success()) {
qWarning() << "Error verifying: " << verifying.errorCode();
return 1;
}
QCA::SecureMessageSignature sign;
sign = verifying.signer();
// todo: dump some data out about the signer
if(verifying.verifySuccess())
{
qDebug() << "Message verified";
if (verifying.verifySuccess()) {
qDebug() << "Message verified";
} else {
qDebug() << "Message failed to verify:" << verifying.errorCode();
qDebug() << "Message failed to verify:" << verifying.errorCode();
}
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@ -28,11 +28,10 @@
class QString;
class QStringList;
namespace QCA
{
class PrivateKey;
class CertificateChain;
class KeyStoreEntry;
namespace QCA {
class PrivateKey;
class CertificateChain;
class KeyStoreEntry;
}
class CertItemStore;
@ -42,105 +41,105 @@ class CertItemPrivateLoaderPrivate;
class CertItem
{
public:
enum StorageType
{
File,
KeyStore
};
enum StorageType
{
File,
KeyStore
};
CertItem();
CertItem(const CertItem &from);
~CertItem();
CertItem & operator=(const CertItem &from);
CertItem();
CertItem(const CertItem &from);
~CertItem();
CertItem &operator=(const CertItem &from);
QString name() const;
QCA::CertificateChain certificateChain() const;
bool havePrivate() const;
StorageType storageType() const; // private key storage type
bool isUsable() const; // file/provider present
QString name() const;
QCA::CertificateChain certificateChain() const;
bool havePrivate() const;
StorageType storageType() const; // private key storage type
bool isUsable() const; // file/provider present
private:
class Private;
QSharedDataPointer<Private> d;
class Private;
QSharedDataPointer<Private> d;
friend class CertItemStore;
friend class CertItemStorePrivate;
friend class CertItemPrivateLoader;
friend class CertItemPrivateLoaderPrivate;
friend class CertItemStore;
friend class CertItemStorePrivate;
friend class CertItemPrivateLoader;
friend class CertItemPrivateLoaderPrivate;
};
class CertItemStore : public QAbstractListModel
{
Q_OBJECT
Q_OBJECT
public:
enum IconType
{
IconCert,
IconCrl,
IconKeyBundle,
IconPgpPub,
IconPgpSec
};
enum IconType
{
IconCert,
IconCrl,
IconKeyBundle,
IconPgpPub,
IconPgpSec
};
CertItemStore(QObject *parent = 0);
~CertItemStore();
CertItemStore(QObject *parent = nullptr);
~CertItemStore();
int idFromRow(int row) const;
int rowFromId(int id) const;
CertItem itemFromId(int id) const;
CertItem itemFromRow(int row) const;
int idFromRow(int row) const;
int rowFromId(int id) const;
CertItem itemFromId(int id) const;
CertItem itemFromRow(int row) const;
QList<CertItem> items() const;
QList<CertItem> items() const;
QStringList save() const;
bool load(const QStringList &in);
QStringList save() const;
bool load(const QStringList &in);
// returns a reqId
int addFromFile(const QString &fileName);
int addFromKeyStore(const QCA::KeyStoreEntry &entry);
int addUser(const QCA::CertificateChain &chain);
// returns a reqId
int addFromFile(const QString &fileName);
int addFromKeyStore(const QCA::KeyStoreEntry &entry);
int addUser(const QCA::CertificateChain &chain);
void updateChain(int id, const QCA::CertificateChain &chain);
void updateChain(int id, const QCA::CertificateChain &chain);
void removeItem(int id);
void removeItem(int id);
void setIcon(IconType type, const QPixmap &icon);
void setIcon(IconType type, const QPixmap &icon);
// reimplemented
int rowCount(const QModelIndex &parent = QModelIndex()) const;
QVariant data(const QModelIndex &index, int role) const;
Qt::ItemFlags flags(const QModelIndex &index) const;
bool setData(const QModelIndex &index, const QVariant &value, int role);
// reimplemented
int rowCount(const QModelIndex &parent = QModelIndex()) const;
QVariant data(const QModelIndex &index, int role) const;
Qt::ItemFlags flags(const QModelIndex &index) const;
bool setData(const QModelIndex &index, const QVariant &value, int role);
signals:
void addSuccess(int reqId, int id);
void addFailed(int reqId);
Q_SIGNALS:
void addSuccess(int reqId, int id);
void addFailed(int reqId);
private:
friend class CertItemStorePrivate;
CertItemStorePrivate *d;
friend class CertItemStorePrivate;
CertItemStorePrivate *d;
friend class CertItemPrivateLoader;
friend class CertItemPrivateLoaderPrivate;
friend class CertItemPrivateLoader;
friend class CertItemPrivateLoaderPrivate;
};
class CertItemPrivateLoader : public QObject
{
Q_OBJECT
Q_OBJECT
public:
explicit CertItemPrivateLoader(CertItemStore *store, QObject *parent = 0);
~CertItemPrivateLoader();
explicit CertItemPrivateLoader(CertItemStore *store, QObject *parent = nullptr);
~CertItemPrivateLoader();
void start(int id);
void start(int id);
QCA::PrivateKey privateKey() const;
QCA::PrivateKey privateKey() const;
signals:
void finished();
Q_SIGNALS:
void finished();
private:
friend class CertItemPrivateLoaderPrivate;
CertItemPrivateLoaderPrivate *d;
friend class CertItemPrivateLoaderPrivate;
CertItemPrivateLoaderPrivate *d;
};
#endif

View File

@ -21,146 +21,165 @@
#include "certviewdlg.h"
#include <QtCore>
#include <QtGui>
#include <QtCrypto>
#include "ui_certview.h"
#include <QtCore>
#include <QtCrypto>
#include <QtGui>
// from qcatool
class InfoType
{
public:
QCA::CertificateInfoType type;
QString varname;
QString shortname;
QString name;
QString desc;
QCA::CertificateInfoType type;
QString varname;
QString shortname;
QString name;
QString desc;
InfoType()
{
}
InfoType()
{
}
InfoType(QCA::CertificateInfoType _type, const QString &_varname, const QString &_shortname, const QString &_name, const QString &_desc) :
type(_type),
varname(_varname),
shortname(_shortname),
name(_name),
desc(_desc)
{
}
InfoType(QCA::CertificateInfoType _type,
const QString & _varname,
const QString & _shortname,
const QString & _name,
const QString & _desc)
: type(_type)
, varname(_varname)
, shortname(_shortname)
, name(_name)
, desc(_desc)
{
}
};
static QList<InfoType> makeInfoTypeList(bool legacyEmail = false)
{
QList<InfoType> out;
out += InfoType(QCA::CommonName, "CommonName", "CN", CertViewDlg::tr("Common Name (CN)"), "Full name, domain, anything");
out += InfoType(QCA::Email, "Email", "", CertViewDlg::tr("Email Address"), "");
if(legacyEmail)
out += InfoType(QCA::EmailLegacy, "EmailLegacy", "", CertViewDlg::tr("PKCS#9 Email Address"), "");
out += InfoType(QCA::Organization, "Organization", "O", CertViewDlg::tr("Organization (O)"), "Company, group, etc");
out += InfoType(QCA::OrganizationalUnit, "OrganizationalUnit", "OU", CertViewDlg::tr("Organizational Unit (OU)"), "Division/branch of organization");
out += InfoType(QCA::Locality, "Locality", "", CertViewDlg::tr("Locality (L)"), "City, shire, part of a state");
out += InfoType(QCA::State, "State", "", CertViewDlg::tr("State (ST)"), "State within the country");
out += InfoType(QCA::Country, "Country", "C", CertViewDlg::tr("Country Code (C)"), "2-letter code");
out += InfoType(QCA::IncorporationLocality, "IncorporationLocality", "", CertViewDlg::tr("Incorporation Locality"), "For EV certificates");
out += InfoType(QCA::IncorporationState, "IncorporationState", "", CertViewDlg::tr("Incorporation State"), "For EV certificates");
out += InfoType(QCA::IncorporationCountry, "IncorporationCountry", "", CertViewDlg::tr("Incorporation Country"), "For EV certificates");
out += InfoType(QCA::URI, "URI", "", CertViewDlg::tr("URI"), "");
out += InfoType(QCA::DNS, "DNS", "", CertViewDlg::tr("Domain Name"), "Domain (dnsName)");
out += InfoType(QCA::IPAddress, "IPAddress", "", CertViewDlg::tr("IP Adddress"), "");
out += InfoType(QCA::XMPP, "XMPP", "", CertViewDlg::tr("XMPP Address (JID)"), "From RFC 3920 (id-on-xmppAddr)");
return out;
QList<InfoType> out;
out += InfoType(
QCA::CommonName, "CommonName", "CN", CertViewDlg::tr("Common Name (CN)"), "Full name, domain, anything");
out += InfoType(QCA::Email, "Email", "", CertViewDlg::tr("Email Address"), "");
if (legacyEmail)
out += InfoType(QCA::EmailLegacy, "EmailLegacy", "", CertViewDlg::tr("PKCS#9 Email Address"), "");
out += InfoType(QCA::Organization, "Organization", "O", CertViewDlg::tr("Organization (O)"), "Company, group, etc");
out += InfoType(QCA::OrganizationalUnit,
"OrganizationalUnit",
"OU",
CertViewDlg::tr("Organizational Unit (OU)"),
"Division/branch of organization");
out += InfoType(QCA::Locality, "Locality", "", CertViewDlg::tr("Locality (L)"), "City, shire, part of a state");
out += InfoType(QCA::State, "State", "", CertViewDlg::tr("State (ST)"), "State within the country");
out += InfoType(QCA::Country, "Country", "C", CertViewDlg::tr("Country Code (C)"), "2-letter code");
out += InfoType(QCA::IncorporationLocality,
"IncorporationLocality",
"",
CertViewDlg::tr("Incorporation Locality"),
"For EV certificates");
out += InfoType(QCA::IncorporationState,
"IncorporationState",
"",
CertViewDlg::tr("Incorporation State"),
"For EV certificates");
out += InfoType(QCA::IncorporationCountry,
"IncorporationCountry",
"",
CertViewDlg::tr("Incorporation Country"),
"For EV certificates");
out += InfoType(QCA::URI, "URI", "", CertViewDlg::tr("URI"), "");
out += InfoType(QCA::DNS, "DNS", "", CertViewDlg::tr("Domain Name"), "Domain (dnsName)");
out += InfoType(QCA::IPAddress, "IPAddress", "", CertViewDlg::tr("IP Adddress"), "");
out += InfoType(QCA::XMPP, "XMPP", "", CertViewDlg::tr("XMPP Address (JID)"), "From RFC 3920 (id-on-xmppAddr)");
return out;
}
static QString try_print_info(const QString &name, const QStringList &values)
{
QString out;
if(!values.isEmpty())
{
QString value = values.join(", ");
out = QString(" ") + CertViewDlg::tr("%1: %2").arg(name, value) + '\n';
}
return out;
QString out;
if (!values.isEmpty()) {
QString value = values.join(", ");
out = QString(" ") + CertViewDlg::tr("%1: %2").arg(name, value) + '\n';
}
return out;
}
static QString print_info(const QString &title, const QCA::CertificateInfo &info)
{
QString out;
QList<InfoType> list = makeInfoTypeList();
out += title + '\n';
foreach(const InfoType &t, list)
out += try_print_info(t.name, info.values(t.type));
return out;
QString out;
QList<InfoType> list = makeInfoTypeList();
out += title + '\n';
foreach (const InfoType &t, list)
out += try_print_info(t.name, info.values(t.type));
return out;
}
static QString cert_info_string(const QCA::Certificate &cert)
{
QString out;
out += CertViewDlg::tr("Serial Number: %1").arg(cert.serialNumber().toString()) + '\n';
out += print_info(CertViewDlg::tr("Subject"), cert.subjectInfo());
out += print_info(CertViewDlg::tr("Issuer"), cert.issuerInfo());
out += CertViewDlg::tr("Validity") + '\n';
out += QString(" ") + CertViewDlg::tr("Not before: %1").arg(cert.notValidBefore().toString()) + '\n';
out += QString(" ") + CertViewDlg::tr("Not after: %1").arg(cert.notValidAfter().toString()) + '\n';
return out;
QString out;
out += CertViewDlg::tr("Serial Number: %1").arg(cert.serialNumber().toString()) + '\n';
out += print_info(CertViewDlg::tr("Subject"), cert.subjectInfo());
out += print_info(CertViewDlg::tr("Issuer"), cert.issuerInfo());
out += CertViewDlg::tr("Validity") + '\n';
out += QString(" ") + CertViewDlg::tr("Not before: %1").arg(cert.notValidBefore().toString()) + '\n';
out += QString(" ") + CertViewDlg::tr("Not after: %1").arg(cert.notValidAfter().toString()) + '\n';
return out;
}
class CertViewDlg::Private : public QObject
{
Q_OBJECT
Q_OBJECT
public:
CertViewDlg *q;
Ui_CertView ui;
QCA::CertificateChain chain;
CertViewDlg * q;
Ui_CertView ui;
QCA::CertificateChain chain;
Private(CertViewDlg *_q) :
QObject(_q),
q(_q)
{
ui.setupUi(q);
connect(ui.cb_chain, SIGNAL(activated(int)), SLOT(cb_activated(int)));
ui.lb_info->setTextInteractionFlags(Qt::TextSelectableByMouse);
}
Private(CertViewDlg *_q)
: QObject(_q)
, q(_q)
{
ui.setupUi(q);
connect(ui.cb_chain, SIGNAL(activated(int)), SLOT(cb_activated(int)));
ui.lb_info->setTextInteractionFlags(Qt::TextSelectableByMouse);
}
void update()
{
QStringList names = QCA::makeFriendlyNames(chain);
ui.cb_chain->clear();
foreach(const QString &s, names)
ui.cb_chain->insertItem(ui.cb_chain->count(), s);
updateInfo();
}
void update()
{
QStringList names = QCA::makeFriendlyNames(chain);
ui.cb_chain->clear();
foreach (const QString &s, names)
ui.cb_chain->insertItem(ui.cb_chain->count(), s);
updateInfo();
}
void updateInfo()
{
int x = ui.cb_chain->currentIndex();
if(x == -1)
{
ui.lb_info->setText("");
return;
}
void updateInfo()
{
int x = ui.cb_chain->currentIndex();
if (x == -1) {
ui.lb_info->setText("");
return;
}
ui.lb_info->setText(cert_info_string(chain[x]));
}
ui.lb_info->setText(cert_info_string(chain[x]));
}
private slots:
void cb_activated(int)
{
updateInfo();
}
private Q_SLOTS:
void cb_activated(int)
{
updateInfo();
}
};
CertViewDlg::CertViewDlg(const QCA::CertificateChain &chain, QWidget *parent) :
QDialog(parent)
CertViewDlg::CertViewDlg(const QCA::CertificateChain &chain, QWidget *parent)
: QDialog(parent)
{
d = new Private(this);
d->chain = chain;
d->update();
d = new Private(this);
d->chain = chain;
d->update();
}
CertViewDlg::~CertViewDlg()
{
delete d;
delete d;
}
#include "certviewdlg.moc"

View File

@ -24,21 +24,20 @@
#include <QDialog>
namespace QCA
{
class CertificateChain;
namespace QCA {
class CertificateChain;
}
class CertViewDlg : public QDialog
{
Q_OBJECT
Q_OBJECT
public:
explicit CertViewDlg(const QCA::CertificateChain &chain, QWidget *parent = 0);
~CertViewDlg();
explicit CertViewDlg(const QCA::CertificateChain &chain, QWidget *parent = 0);
~CertViewDlg();
private:
class Private;
Private *d;
class Private;
Private *d;
};
#endif

View File

@ -21,405 +21,394 @@
#include "keyselectdlg.h"
#include <QtCore>
#include <QtGui>
#include <QtCrypto>
#include <QPushButton>
#include "ui_keyselect.h"
#include <QMenu>
#include <QMessageBox>
#include "ui_keyselect.h"
#include <QPushButton>
#include <QtCore>
#include <QtCrypto>
#include <QtGui>
#define ONLY_SHOW_KEYBUNDLE
typedef QMap<KeySelectDlg::IconType,QPixmap> KeyStoreIconset;
typedef QMap<KeySelectDlg::IconType, QPixmap> KeyStoreIconset;
class KeyStoreItemShared
{
public:
KeyStoreIconset iconset;
QString notAvailableString;
KeyStoreIconset iconset;
QString notAvailableString;
};
class KeyStoreItem : public QStandardItem
{
public:
enum Type
{
Store = UserType,
Entry
};
enum Type
{
Store = UserType,
Entry
};
enum Role
{
NameRole = Qt::UserRole,
SubTypeRole,
AvailabilityRole,
PositionRole
};
enum Role
{
NameRole = Qt::UserRole,
SubTypeRole,
AvailabilityRole,
PositionRole
};
QPixmap entryTypeToIcon(QCA::KeyStoreEntry::Type type) const
{
QPixmap out;
if(!_shared)
return out;
const KeyStoreIconset &iconset = _shared->iconset;
switch(type)
{
case QCA::KeyStoreEntry::TypeKeyBundle: out = iconset[KeySelectDlg::IconKeyBundle]; break;
case QCA::KeyStoreEntry::TypeCertificate: out = iconset[KeySelectDlg::IconCert]; break;
case QCA::KeyStoreEntry::TypeCRL: out = iconset[KeySelectDlg::IconCrl]; break;
case QCA::KeyStoreEntry::TypePGPSecretKey: out = iconset[KeySelectDlg::IconPgpSec]; break;
case QCA::KeyStoreEntry::TypePGPPublicKey: out = iconset[KeySelectDlg::IconPgpPub]; break;
default: break;
}
return out;
}
QPixmap entryTypeToIcon(QCA::KeyStoreEntry::Type type) const
{
QPixmap out;
if (!_shared)
return out;
const KeyStoreIconset &iconset = _shared->iconset;
switch (type) {
case QCA::KeyStoreEntry::TypeKeyBundle:
out = iconset[KeySelectDlg::IconKeyBundle];
break;
case QCA::KeyStoreEntry::TypeCertificate:
out = iconset[KeySelectDlg::IconCert];
break;
case QCA::KeyStoreEntry::TypeCRL:
out = iconset[KeySelectDlg::IconCrl];
break;
case QCA::KeyStoreEntry::TypePGPSecretKey:
out = iconset[KeySelectDlg::IconPgpSec];
break;
case QCA::KeyStoreEntry::TypePGPPublicKey:
out = iconset[KeySelectDlg::IconPgpPub];
break;
default:
break;
}
return out;
}
Type _type;
KeyStoreItemShared *_shared;
Type _type;
KeyStoreItemShared *_shared;
QCA::KeyStore *keyStore;
QCA::KeyStoreEntry keyStoreEntry;
QCA::KeyStore * keyStore;
QCA::KeyStoreEntry keyStoreEntry;
KeyStoreItem(Type type, KeyStoreItemShared *shared) :
_type(type),
_shared(shared)
{
setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
}
KeyStoreItem(Type type, KeyStoreItemShared *shared)
: _type(type)
, _shared(shared)
{
setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
}
void setStore(const QString &name, QCA::KeyStore::Type type)
{
setData(name, NameRole);
setData((int)type, SubTypeRole);
}
void setStore(const QString &name, QCA::KeyStore::Type type)
{
setData(name, NameRole);
setData((int)type, SubTypeRole);
}
void setEntry(const QString &name, QCA::KeyStoreEntry::Type type, bool available, int pos)
{
setData(name, NameRole);
setData((int)type, SubTypeRole);
setData(available, AvailabilityRole);
setData(pos, PositionRole);
}
void setEntry(const QString &name, QCA::KeyStoreEntry::Type type, bool available, int pos)
{
setData(name, NameRole);
setData((int)type, SubTypeRole);
setData(available, AvailabilityRole);
setData(pos, PositionRole);
}
virtual QVariant data(int role) const
{
if(role == Qt::DisplayRole)
{
if(_type == Store)
{
return data(NameRole).toString();
}
else if(_type == Entry)
{
QString str = data(NameRole).toString();
if(_shared && !data(AvailabilityRole).toBool())
str += QString(" ") + _shared->notAvailableString;
return str;
}
else
return QStandardItem::data(role);
}
else if(role == Qt::DecorationRole)
{
if(_type == Entry)
{
QCA::KeyStoreEntry::Type type = (QCA::KeyStoreEntry::Type)data(SubTypeRole).toInt();
return entryTypeToIcon(type);
}
else
return QStandardItem::data(role);
}
else
return QStandardItem::data(role);
}
virtual QVariant data(int role) const
{
if (role == Qt::DisplayRole) {
if (_type == Store) {
return data(NameRole).toString();
} else if (_type == Entry) {
QString str = data(NameRole).toString();
if (_shared && !data(AvailabilityRole).toBool())
str += QString(" ") + _shared->notAvailableString;
return str;
} else
return QStandardItem::data(role);
} else if (role == Qt::DecorationRole) {
if (_type == Entry) {
QCA::KeyStoreEntry::Type type = (QCA::KeyStoreEntry::Type)data(SubTypeRole).toInt();
return entryTypeToIcon(type);
} else
return QStandardItem::data(role);
} else
return QStandardItem::data(role);
}
virtual int type() const
{
return _type;
}
virtual int type() const
{
return _type;
}
virtual QStandardItem *clone() const
{
return new KeyStoreItem(*this);
}
virtual QStandardItem *clone() const
{
return new KeyStoreItem(*this);
}
};
class KeyStoreModel : public QStandardItemModel
{
Q_OBJECT
Q_OBJECT
public:
KeyStoreItemShared shared;
KeyStoreItemShared shared;
QCA::KeyStoreManager ksm;
QCA::KeyStoreManager ksm;
KeyStoreModel(QObject *parent = 0) :
QStandardItemModel(parent), ksm(this)
{
shared.notAvailableString = tr("(not available)");
KeyStoreModel(QObject *parent = 0)
: QStandardItemModel(parent)
, ksm(this)
{
shared.notAvailableString = tr("(not available)");
// make sure keystores are started
QCA::KeyStoreManager::start();
// make sure keystores are started
QCA::KeyStoreManager::start();
connect(&ksm, SIGNAL(keyStoreAvailable(const QString &)), SLOT(ks_available(const QString &)));
QStringList list = ksm.keyStores();
foreach(const QString &s, list)
ks_available(s);
connect(&ksm, SIGNAL(keyStoreAvailable(const QString &)), SLOT(ks_available(const QString &)));
QStringList list = ksm.keyStores();
foreach (const QString &s, list)
ks_available(s);
setSortRole(KeyStoreItem::PositionRole);
}
setSortRole(KeyStoreItem::PositionRole);
}
KeyStoreItem *itemFromStore(QCA::KeyStore *ks) const
{
for(int n = 0; n < rowCount(); ++n)
{
KeyStoreItem *i = (KeyStoreItem *)item(n);
if(i->keyStore == ks)
return i;
}
return 0;
}
KeyStoreItem *itemFromStore(QCA::KeyStore *ks) const
{
for (int n = 0; n < rowCount(); ++n) {
KeyStoreItem *i = (KeyStoreItem *)item(n);
if (i->keyStore == ks)
return i;
}
return 0;
}
private slots:
void ks_available(const QString &keyStoreId)
{
QCA::KeyStore *ks = new QCA::KeyStore(keyStoreId, &ksm);
private Q_SLOTS:
void ks_available(const QString &keyStoreId)
{
QCA::KeyStore *ks = new QCA::KeyStore(keyStoreId, &ksm);
#ifdef ONLY_SHOW_KEYBUNDLE
// only list stores containing keybundles (non-pgp identities)
if(!ks->holdsIdentities() || ks->type() == QCA::KeyStore::PGPKeyring)
return;
// only list stores containing keybundles (non-pgp identities)
if (!ks->holdsIdentities() || ks->type() == QCA::KeyStore::PGPKeyring)
return;
#endif
connect(ks, SIGNAL(updated()), SLOT(ks_updated()));
connect(ks, SIGNAL(unavailable()), SLOT(ks_unavailable()));
connect(ks, SIGNAL(updated()), SLOT(ks_updated()));
connect(ks, SIGNAL(unavailable()), SLOT(ks_unavailable()));
KeyStoreItem *store_item = new KeyStoreItem(KeyStoreItem::Store, &shared);
store_item->setStore(ks->name(), ks->type());
store_item->keyStore = ks;
ks->startAsynchronousMode();
appendRow(store_item);
}
KeyStoreItem *store_item = new KeyStoreItem(KeyStoreItem::Store, &shared);
store_item->setStore(ks->name(), ks->type());
store_item->keyStore = ks;
ks->startAsynchronousMode();
appendRow(store_item);
}
void ks_updated()
{
QCA::KeyStore *ks = (QCA::KeyStore *)sender();
KeyStoreItem *store_item = itemFromStore(ks);
Q_ASSERT(store_item);
void ks_updated()
{
QCA::KeyStore *ks = (QCA::KeyStore *)sender();
KeyStoreItem * store_item = itemFromStore(ks);
Q_ASSERT(store_item);
QList<QCA::KeyStoreEntry> newEntries = ks->entryList();
QList<QCA::KeyStoreEntry> newEntries = ks->entryList();
#ifdef ONLY_SHOW_KEYBUNDLE
// ignore entries that are not keybundles
for(int n = 0; n < newEntries.count(); ++n)
{
if(newEntries[n].type() != QCA::KeyStoreEntry::TypeKeyBundle)
{
newEntries.removeAt(n);
--n; // adjust position
}
}
// ignore entries that are not keybundles
for (int n = 0; n < newEntries.count(); ++n) {
if (newEntries[n].type() != QCA::KeyStoreEntry::TypeKeyBundle) {
newEntries.removeAt(n);
--n; // adjust position
}
}
#endif
// update the store item itself
store_item->setStore(ks->name(), ks->type());
// update the store item itself
store_item->setStore(ks->name(), ks->type());
// handle removed child entries
for(int n = 0; n < store_item->rowCount(); ++n)
{
KeyStoreItem *i = (KeyStoreItem *)store_item->child(n);
// handle removed child entries
for (int n = 0; n < store_item->rowCount(); ++n) {
KeyStoreItem *i = (KeyStoreItem *)store_item->child(n);
// is the existing entry in the new list?
bool found = false;
foreach(const QCA::KeyStoreEntry &ne, newEntries)
{
if(ne.id() == i->keyStoreEntry.id())
{
found = true;
break;
}
}
// is the existing entry in the new list?
bool found = false;
foreach (const QCA::KeyStoreEntry &ne, newEntries) {
if (ne.id() == i->keyStoreEntry.id()) {
found = true;
break;
}
}
// if not, remove it
if(!found)
{
store_item->removeRow(n);
--n; // adjust position
}
}
// if not, remove it
if (!found) {
store_item->removeRow(n);
--n; // adjust position
}
}
// handle added/updated child entries
for(int n = 0; n < newEntries.count(); ++n)
{
const QCA::KeyStoreEntry &ne = newEntries[n];
// handle added/updated child entries
for (int n = 0; n < newEntries.count(); ++n) {
const QCA::KeyStoreEntry &ne = newEntries[n];
// was this entry in the original list?
KeyStoreItem *entry_item = 0;
for(int k = 0; k < store_item->rowCount(); ++k)
{
KeyStoreItem *i = (KeyStoreItem *)store_item->child(k);
if(i->keyStoreEntry.id() == ne.id())
{
entry_item = i;
break;
}
}
// was this entry in the original list?
KeyStoreItem *entry_item = 0;
for (int k = 0; k < store_item->rowCount(); ++k) {
KeyStoreItem *i = (KeyStoreItem *)store_item->child(k);
if (i->keyStoreEntry.id() == ne.id()) {
entry_item = i;
break;
}
}
// if not, add it
if(!entry_item)
{
entry_item = new KeyStoreItem(KeyStoreItem::Entry, &shared);
entry_item->keyStoreEntry = ne;
entry_item->setEntry(newEntries[n].name(), newEntries[n].type(), newEntries[n].isAvailable(), n);
store_item->appendRow(entry_item);
}
// if so, update it
else
{
entry_item->keyStoreEntry = ne;
entry_item->setEntry(newEntries[n].name(), newEntries[n].type(), newEntries[n].isAvailable(), n);
}
}
// if not, add it
if (!entry_item) {
entry_item = new KeyStoreItem(KeyStoreItem::Entry, &shared);
entry_item->keyStoreEntry = ne;
entry_item->setEntry(newEntries[n].name(), newEntries[n].type(), newEntries[n].isAvailable(), n);
store_item->appendRow(entry_item);
}
// if so, update it
else {
entry_item->keyStoreEntry = ne;
entry_item->setEntry(newEntries[n].name(), newEntries[n].type(), newEntries[n].isAvailable(), n);
}
}
store_item->sortChildren(0);
}
store_item->sortChildren(0);
}
void ks_unavailable()
{
QCA::KeyStore *ks = (QCA::KeyStore *)sender();
KeyStoreItem *store_item = itemFromStore(ks);
Q_ASSERT(store_item);
void ks_unavailable()
{
QCA::KeyStore *ks = (QCA::KeyStore *)sender();
KeyStoreItem * store_item = itemFromStore(ks);
Q_ASSERT(store_item);
store_item->removeRows(0, store_item->rowCount());
removeRow(store_item->row());
delete ks;
}
store_item->removeRows(0, store_item->rowCount());
removeRow(store_item->row());
delete ks;
}
};
class KeySelectDlg::Private : public QObject
{
Q_OBJECT
Q_OBJECT
public:
KeySelectDlg *q;
Ui_KeySelect ui;
KeyStoreModel *model;
QCA::KeyStoreEntry cur_entry;
QAction *actionView;
KeySelectDlg * q;
Ui_KeySelect ui;
KeyStoreModel * model;
QCA::KeyStoreEntry cur_entry;
QAction * actionView;
Private(KeySelectDlg *_q) :
QObject(_q),
q(_q)
{
ui.setupUi(q);
Private(KeySelectDlg *_q)
: QObject(_q)
, q(_q)
{
ui.setupUi(q);
model = new KeyStoreModel(this);
connect(&model->ksm, SIGNAL(busyStarted()), SLOT(ksm_busyStarted()));
connect(&model->ksm, SIGNAL(busyFinished()), SLOT(ksm_busyFinished()));
if(model->ksm.isBusy())
ksm_busyStarted();
model = new KeyStoreModel(this);
connect(&model->ksm, SIGNAL(busyStarted()), SLOT(ksm_busyStarted()));
connect(&model->ksm, SIGNAL(busyFinished()), SLOT(ksm_busyFinished()));
if (model->ksm.isBusy())
ksm_busyStarted();
ui.lv_stores->header()->hide();
ui.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
ui.lv_stores->setModel(model);
ui.lv_stores->setContextMenuPolicy(Qt::CustomContextMenu);
connect(ui.lv_stores->selectionModel(), SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)), SLOT(stores_selectionChanged(const QItemSelection &, const QItemSelection &)));
connect(ui.lv_stores, SIGNAL(customContextMenuRequested(const QPoint &)), SLOT(stores_customContextMenuRequested(const QPoint &)));
ui.lv_stores->header()->hide();
ui.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
ui.lv_stores->setModel(model);
ui.lv_stores->setContextMenuPolicy(Qt::CustomContextMenu);
connect(ui.lv_stores->selectionModel(),
SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)),
SLOT(stores_selectionChanged(const QItemSelection &, const QItemSelection &)));
connect(ui.lv_stores,
SIGNAL(customContextMenuRequested(const QPoint &)),
SLOT(stores_customContextMenuRequested(const QPoint &)));
actionView = new QAction(tr("&View"), this);
connect(actionView, SIGNAL(triggered()), SLOT(view()));
actionView->setEnabled(false);
}
actionView = new QAction(tr("&View"), this);
connect(actionView, SIGNAL(triggered()), SLOT(view()));
actionView->setEnabled(false);
}
private slots:
void ksm_busyStarted()
{
ui.lb_busy->setText(tr("Looking for devices..."));
}
private Q_SLOTS:
void ksm_busyStarted()
{
ui.lb_busy->setText(tr("Looking for devices..."));
}
void ksm_busyFinished()
{
ui.lb_busy->setText("");
}
void ksm_busyFinished()
{
ui.lb_busy->setText("");
}
void stores_selectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
{
Q_UNUSED(deselected);
void stores_selectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
{
Q_UNUSED(deselected);
KeyStoreItem *i = 0;
if(!selected.indexes().isEmpty())
{
QModelIndex index = selected.indexes().first();
i = (KeyStoreItem *)model->itemFromIndex(index);
}
KeyStoreItem *i = 0;
if (!selected.indexes().isEmpty()) {
QModelIndex index = selected.indexes().first();
i = (KeyStoreItem *)model->itemFromIndex(index);
}
bool viewable = false;
bool choosable = false;
if(i && i->type() == KeyStoreItem::Entry)
{
QCA::KeyStoreEntry entry = i->keyStoreEntry;
if(entry.type() == QCA::KeyStoreEntry::TypeKeyBundle)
{
viewable = true;
choosable = true;
cur_entry = entry;
}
}
bool viewable = false;
bool choosable = false;
if (i && i->type() == KeyStoreItem::Entry) {
QCA::KeyStoreEntry entry = i->keyStoreEntry;
if (entry.type() == QCA::KeyStoreEntry::TypeKeyBundle) {
viewable = true;
choosable = true;
cur_entry = entry;
}
}
if(!choosable)
cur_entry = QCA::KeyStoreEntry();
if (!choosable)
cur_entry = QCA::KeyStoreEntry();
actionView->setEnabled(viewable);
actionView->setEnabled(viewable);
QPushButton *ok = ui.buttonBox->button(QDialogButtonBox::Ok);
if(choosable && !ok->isEnabled())
ok->setEnabled(true);
else if(!choosable && ok->isEnabled())
ok->setEnabled(false);
}
QPushButton *ok = ui.buttonBox->button(QDialogButtonBox::Ok);
if (choosable && !ok->isEnabled())
ok->setEnabled(true);
else if (!choosable && ok->isEnabled())
ok->setEnabled(false);
}
void stores_customContextMenuRequested(const QPoint &pos)
{
QItemSelection selection = ui.lv_stores->selectionModel()->selection();
if(selection.indexes().isEmpty())
return;
void stores_customContextMenuRequested(const QPoint &pos)
{
QItemSelection selection = ui.lv_stores->selectionModel()->selection();
if (selection.indexes().isEmpty())
return;
QModelIndex index = selection.indexes().first();
KeyStoreItem *i = (KeyStoreItem *)model->itemFromIndex(index);
if(i && i->type() == KeyStoreItem::Entry)
{
QMenu menu(q);
menu.addAction(actionView);
menu.exec(ui.lv_stores->viewport()->mapToGlobal(pos));
}
}
QModelIndex index = selection.indexes().first();
KeyStoreItem *i = (KeyStoreItem *)model->itemFromIndex(index);
if (i && i->type() == KeyStoreItem::Entry) {
QMenu menu(q);
menu.addAction(actionView);
menu.exec(ui.lv_stores->viewport()->mapToGlobal(pos));
}
}
void view()
{
emit q->viewCertificate(cur_entry.keyBundle().certificateChain());
}
void view()
{
emit q->viewCertificate(cur_entry.keyBundle().certificateChain());
}
};
KeySelectDlg::KeySelectDlg(QWidget *parent) :
QDialog(parent)
KeySelectDlg::KeySelectDlg(QWidget *parent)
: QDialog(parent)
{
d = new Private(this);
d = new Private(this);
}
KeySelectDlg::~KeySelectDlg()
{
delete d;
delete d;
}
void KeySelectDlg::setIcon(IconType type, const QPixmap &icon)
{
d->model->shared.iconset[type] = icon;
d->model->shared.iconset[type] = icon;
}
void KeySelectDlg::accept()
{
QCA::KeyStoreEntry entry = d->cur_entry;
QDialog::accept();
emit selected(entry);
QCA::KeyStoreEntry entry = d->cur_entry;
QDialog::accept();
emit selected(entry);
}
#include "keyselectdlg.moc"

View File

@ -26,41 +26,40 @@
class QPixmap;
namespace QCA
{
class CertificateChain;
class KeyStoreEntry;
namespace QCA {
class CertificateChain;
class KeyStoreEntry;
}
class KeySelectDlg : public QDialog
{
Q_OBJECT
Q_OBJECT
public:
enum IconType
{
IconCert,
IconCrl,
IconKeyBundle,
IconPgpPub,
IconPgpSec
};
enum IconType
{
IconCert,
IconCrl,
IconKeyBundle,
IconPgpPub,
IconPgpSec
};
KeySelectDlg(QWidget *parent = 0);
~KeySelectDlg();
KeySelectDlg(QWidget *parent = 0);
~KeySelectDlg();
void setIcon(IconType type, const QPixmap &icon);
void setIcon(IconType type, const QPixmap &icon);
signals:
void selected(const QCA::KeyStoreEntry &entry);
void viewCertificate(const QCA::CertificateChain &chain);
Q_SIGNALS:
void selected(const QCA::KeyStoreEntry &entry);
void viewCertificate(const QCA::CertificateChain &chain);
protected slots:
virtual void accept();
virtual void accept();
private:
class Private;
friend class Private;
Private *d;
class Private;
friend class Private;
Private *d;
};
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -30,18 +30,18 @@
class Pkcs11ConfigDlg : public QDialog
{
public:
Pkcs11ConfigDlg(QWidget *parent = 0);
Pkcs11ConfigDlg(const QString &providerName, const QVariantMap &config, QWidget *parent = 0);
~Pkcs11ConfigDlg();
Pkcs11ConfigDlg(QWidget *parent = 0);
Pkcs11ConfigDlg(const QString &providerName, const QVariantMap &config, QWidget *parent = 0);
~Pkcs11ConfigDlg();
static bool isSupported();
static bool isSupported();
protected slots:
virtual void done(int r);
virtual void done(int r);
private:
class Private;
Private *d;
class Private;
Private *d;
};
#endif

View File

@ -21,301 +21,278 @@
#include "prompter.h"
#include <QtCore>
#include <QtGui>
#include <QtCrypto>
#include <QMessageBox>
#include <QInputDialog>
#include <QApplication>
#include <QInputDialog>
#include <QMessageBox>
#include <QtCore>
#include <QtCrypto>
#include <QtGui>
class Prompter::Private : public QObject
{
Q_OBJECT
Q_OBJECT
public:
Prompter *q;
Prompter *q;
class Item
{
public:
int id;
QCA::Event event;
};
class Item
{
public:
int id;
QCA::Event event;
};
QCA::EventHandler handler;
QList<Item> pending;
bool prompting;
QMessageBox *token_prompt;
bool auto_accept;
QCA::EventHandler handler;
QList<Item> pending;
bool prompting;
QMessageBox * token_prompt;
bool auto_accept;
QCA::KeyStoreManager ksm;
QList<QCA::KeyStore*> keyStores;
QCA::KeyStoreManager ksm;
QList<QCA::KeyStore *> keyStores;
Private(Prompter *_q) :
QObject(_q),
q(_q),
handler(this),
prompting(false),
token_prompt(0),
ksm(this)
{
connect(&handler, SIGNAL(eventReady(int, const QCA::Event &)), SLOT(ph_eventReady(int, const QCA::Event &)));
handler.start();
Private(Prompter *_q)
: QObject(_q)
, q(_q)
, handler(this)
, prompting(false)
, token_prompt(0)
, ksm(this)
{
connect(&handler, SIGNAL(eventReady(int, const QCA::Event &)), SLOT(ph_eventReady(int, const QCA::Event &)));
handler.start();
connect(&ksm, SIGNAL(keyStoreAvailable(const QString &)), SLOT(ks_available(const QString &)));
foreach(const QString &keyStoreId, ksm.keyStores())
ks_available(keyStoreId);
}
connect(&ksm, SIGNAL(keyStoreAvailable(const QString &)), SLOT(ks_available(const QString &)));
foreach (const QString &keyStoreId, ksm.keyStores())
ks_available(keyStoreId);
}
~Private()
{
qDeleteAll(keyStores);
~Private()
{
qDeleteAll(keyStores);
while(!pending.isEmpty())
handler.reject(pending.takeFirst().id);
}
while (!pending.isEmpty())
handler.reject(pending.takeFirst().id);
}
private slots:
void ph_eventReady(int id, const QCA::Event &event)
{
Item i;
i.id = id;
i.event = event;
pending += i;
nextEvent();
}
private Q_SLOTS:
void ph_eventReady(int id, const QCA::Event &event)
{
Item i;
i.id = id;
i.event = event;
pending += i;
nextEvent();
}
void nextEvent()
{
if(prompting || pending.isEmpty())
return;
void nextEvent()
{
if (prompting || pending.isEmpty())
return;
prompting = true;
prompting = true;
const Item &i = pending.first();
const int &id = i.id;
const QCA::Event &event = i.event;
const Item & i = pending.first();
const int & id = i.id;
const QCA::Event &event = i.event;
if(event.type() == QCA::Event::Password)
{
QCA::SecureArray known = q->knownPassword(event);
if(!known.isEmpty())
{
handler.submitPassword(id, known);
goto end;
}
if (event.type() == QCA::Event::Password) {
QCA::SecureArray known = q->knownPassword(event);
if (!known.isEmpty()) {
handler.submitPassword(id, known);
goto end;
}
QString type = Prompter::tr("password");
if(event.passwordStyle() == QCA::Event::StylePassphrase)
type = Prompter::tr("passphrase");
else if(event.passwordStyle() == QCA::Event::StylePIN)
type = Prompter::tr("PIN");
QString type = Prompter::tr("password");
if (event.passwordStyle() == QCA::Event::StylePassphrase)
type = Prompter::tr("passphrase");
else if (event.passwordStyle() == QCA::Event::StylePIN)
type = Prompter::tr("PIN");
QString str;
if(event.source() == QCA::Event::KeyStore)
{
QString name;
QCA::KeyStoreEntry entry = event.keyStoreEntry();
if(!entry.isNull())
{
name = entry.name();
}
else
{
if(event.keyStoreInfo().type() == QCA::KeyStore::SmartCard)
name = Prompter::tr("the '%1' token").arg(event.keyStoreInfo().name());
else
name = event.keyStoreInfo().name();
}
str = Prompter::tr("Enter %1 for %2").arg(type, name);
}
else if(!event.fileName().isEmpty())
{
QFileInfo fi(event.fileName());
str = Prompter::tr("Enter %1 for %2:").arg(type, fi.fileName());
}
else
str = Prompter::tr("Enter %1:").arg(type);
QString str;
if (event.source() == QCA::Event::KeyStore) {
QString name;
QCA::KeyStoreEntry entry = event.keyStoreEntry();
if (!entry.isNull()) {
name = entry.name();
} else {
if (event.keyStoreInfo().type() == QCA::KeyStore::SmartCard)
name = Prompter::tr("the '%1' token").arg(event.keyStoreInfo().name());
else
name = event.keyStoreInfo().name();
}
str = Prompter::tr("Enter %1 for %2").arg(type, name);
} else if (!event.fileName().isEmpty()) {
QFileInfo fi(event.fileName());
str = Prompter::tr("Enter %1 for %2:").arg(type, fi.fileName());
} else
str = Prompter::tr("Enter %1:").arg(type);
bool ok;
QString pass = QInputDialog::getText(0, QApplication::instance()->applicationName() + ": " + tr("Prompt"), str, QLineEdit::Password, QString(), &ok);
if(ok)
{
QCA::SecureArray password = pass.toUtf8();
q->userSubmitted(password, event);
handler.submitPassword(id, password);
}
else
handler.reject(id);
}
else if(event.type() == QCA::Event::Token)
{
// even though we're being prompted for a missing token,
// we should still check if the token is present, due to
// a possible race between insert and token request.
bool found = false;
bool ok;
QString pass = QInputDialog::getText(0,
QApplication::instance()->applicationName() + ": " + tr("Prompt"),
str,
QLineEdit::Password,
QString(),
&ok);
if (ok) {
QCA::SecureArray password = pass.toUtf8();
q->userSubmitted(password, event);
handler.submitPassword(id, password);
} else
handler.reject(id);
} else if (event.type() == QCA::Event::Token) {
// even though we're being prompted for a missing token,
// we should still check if the token is present, due to
// a possible race between insert and token request.
bool found = false;
// token-only
if(event.keyStoreEntry().isNull())
{
foreach(QCA::KeyStore *ks, keyStores)
{
if(ks->id() == event.keyStoreInfo().id())
{
found = true;
break;
}
}
}
// token-entry
else
{
QCA::KeyStoreEntry kse = event.keyStoreEntry();
// token-only
if (event.keyStoreEntry().isNull()) {
foreach (QCA::KeyStore *ks, keyStores) {
if (ks->id() == event.keyStoreInfo().id()) {
found = true;
break;
}
}
}
// token-entry
else {
QCA::KeyStoreEntry kse = event.keyStoreEntry();
QCA::KeyStore *ks = 0;
foreach(QCA::KeyStore *i, keyStores)
{
if(i->id() == event.keyStoreInfo().id())
{
ks = i;
break;
}
}
if(ks)
{
QList<QCA::KeyStoreEntry> list = ks->entryList();
foreach(const QCA::KeyStoreEntry &e, list)
{
if(e.id() == kse.id() && kse.isAvailable())
{
found = true;
break;
}
}
}
}
if(found)
{
// auto-accept
handler.tokenOkay(id);
return;
}
QCA::KeyStore *ks = 0;
foreach (QCA::KeyStore *i, keyStores) {
if (i->id() == event.keyStoreInfo().id()) {
ks = i;
break;
}
}
if (ks) {
QList<QCA::KeyStoreEntry> list = ks->entryList();
foreach (const QCA::KeyStoreEntry &e, list) {
if (e.id() == kse.id() && kse.isAvailable()) {
found = true;
break;
}
}
}
}
if (found) {
// auto-accept
handler.tokenOkay(id);
return;
}
QCA::KeyStoreEntry entry = event.keyStoreEntry();
QString name;
if(!entry.isNull())
{
name = Prompter::tr("Please make %1 (of %2) available").arg(entry.name(), entry.storeName());
}
else
{
name = Prompter::tr("Please insert the '%1' token").arg(event.keyStoreInfo().name());
}
QCA::KeyStoreEntry entry = event.keyStoreEntry();
QString name;
if (!entry.isNull()) {
name = Prompter::tr("Please make %1 (of %2) available").arg(entry.name(), entry.storeName());
} else {
name = Prompter::tr("Please insert the '%1' token").arg(event.keyStoreInfo().name());
}
QString str = Prompter::tr("%1 and click OK.").arg(name);
QString str = Prompter::tr("%1 and click OK.").arg(name);
QMessageBox msgBox(QMessageBox::Information, QApplication::instance()->applicationName() + ": " + tr("Prompt"), str, QMessageBox::Ok | QMessageBox::Cancel, 0);
token_prompt = &msgBox;
auto_accept = false;
if(msgBox.exec() == QMessageBox::Ok || auto_accept)
handler.tokenOkay(id);
else
handler.reject(id);
token_prompt = 0;
}
else
handler.reject(id);
QMessageBox msgBox(QMessageBox::Information,
QApplication::instance()->applicationName() + ": " + tr("Prompt"),
str,
QMessageBox::Ok | QMessageBox::Cancel,
0);
token_prompt = &msgBox;
auto_accept = false;
if (msgBox.exec() == QMessageBox::Ok || auto_accept)
handler.tokenOkay(id);
else
handler.reject(id);
token_prompt = 0;
} else
handler.reject(id);
end:
pending.removeFirst();
prompting = false;
end:
pending.removeFirst();
prompting = false;
if(!pending.isEmpty())
QMetaObject::invokeMethod(this, "nextEvent", Qt::QueuedConnection);
}
if (!pending.isEmpty())
QMetaObject::invokeMethod(this, "nextEvent", Qt::QueuedConnection);
}
void ks_available(const QString &keyStoreId)
{
QCA::KeyStore *ks = new QCA::KeyStore(keyStoreId, &ksm);
connect(ks, SIGNAL(updated()), SLOT(ks_updated()));
connect(ks, SIGNAL(unavailable()), SLOT(ks_unavailable()));
keyStores += ks;
ks->startAsynchronousMode();
void ks_available(const QString &keyStoreId)
{
QCA::KeyStore *ks = new QCA::KeyStore(keyStoreId, &ksm);
connect(ks, SIGNAL(updated()), SLOT(ks_updated()));
connect(ks, SIGNAL(unavailable()), SLOT(ks_unavailable()));
keyStores += ks;
ks->startAsynchronousMode();
// are we currently in a token-only prompt?
if(token_prompt && pending.first().event.type() == QCA::Event::Token && pending.first().event.keyStoreEntry().isNull())
{
// was the token we're looking for just inserted?
if(pending.first().event.keyStoreInfo().id() == keyStoreId)
{
// auto-accept
auto_accept = true;
token_prompt->accept();
}
}
}
// are we currently in a token-only prompt?
if (token_prompt && pending.first().event.type() == QCA::Event::Token &&
pending.first().event.keyStoreEntry().isNull()) {
// was the token we're looking for just inserted?
if (pending.first().event.keyStoreInfo().id() == keyStoreId) {
// auto-accept
auto_accept = true;
token_prompt->accept();
}
}
}
void ks_unavailable()
{
QCA::KeyStore *ks = (QCA::KeyStore *)sender();
keyStores.removeAll(ks);
delete ks;
}
void ks_unavailable()
{
QCA::KeyStore *ks = (QCA::KeyStore *)sender();
keyStores.removeAll(ks);
delete ks;
}
void ks_updated()
{
QCA::KeyStore *ks = (QCA::KeyStore *)sender();
void ks_updated()
{
QCA::KeyStore *ks = (QCA::KeyStore *)sender();
// are we currently in a token-entry prompt?
if(token_prompt && pending.first().event.type() == QCA::Event::Token && !pending.first().event.keyStoreEntry().isNull())
{
QCA::KeyStoreEntry kse = pending.first().event.keyStoreEntry();
// are we currently in a token-entry prompt?
if (token_prompt && pending.first().event.type() == QCA::Event::Token &&
!pending.first().event.keyStoreEntry().isNull()) {
QCA::KeyStoreEntry kse = pending.first().event.keyStoreEntry();
// was the token of the entry we're looking for updated?
if(pending.first().event.keyStoreInfo().id() == ks->id())
{
// is the entry available?
bool avail = false;
QList<QCA::KeyStoreEntry> list = ks->entryList();
foreach(const QCA::KeyStoreEntry &e, list)
{
if(e.id() == kse.id())
{
avail = kse.isAvailable();
break;
}
}
if(avail)
{
// auto-accept
auto_accept = true;
token_prompt->accept();
}
}
}
}
// was the token of the entry we're looking for updated?
if (pending.first().event.keyStoreInfo().id() == ks->id()) {
// is the entry available?
bool avail = false;
QList<QCA::KeyStoreEntry> list = ks->entryList();
foreach (const QCA::KeyStoreEntry &e, list) {
if (e.id() == kse.id()) {
avail = kse.isAvailable();
break;
}
}
if (avail) {
// auto-accept
auto_accept = true;
token_prompt->accept();
}
}
}
}
};
Prompter::Prompter(QObject *parent) :
QObject(parent)
Prompter::Prompter(QObject *parent)
: QObject(parent)
{
d = new Private(this);
d = new Private(this);
}
Prompter::~Prompter()
{
delete d;
delete d;
}
QCA::SecureArray Prompter::knownPassword(const QCA::Event &event)
{
Q_UNUSED(event);
return QCA::SecureArray();
Q_UNUSED(event);
return QCA::SecureArray();
}
void Prompter::userSubmitted(const QCA::SecureArray &password, const QCA::Event &event)
{
Q_UNUSED(password);
Q_UNUSED(event);
Q_UNUSED(password);
Q_UNUSED(event);
}
#include "prompter.moc"

View File

@ -24,34 +24,33 @@
#include <QObject>
namespace QCA
{
class SecureArray;
class Event;
namespace QCA {
class SecureArray;
class Event;
}
class Prompter : public QObject
{
Q_OBJECT
Q_OBJECT
public:
Prompter(QObject *parent = 0);
~Prompter();
Prompter(QObject *parent = nullptr);
~Prompter();
protected:
// called with every password event, to check for a known value.
// reimplement it to provide known/cached passwords.
virtual QCA::SecureArray knownPassword(const QCA::Event &event);
// called with every password event, to check for a known value.
// reimplement it to provide known/cached passwords.
virtual QCA::SecureArray knownPassword(const QCA::Event &event);
// called when a user-entered password is submitted. note that this
// does not mean the password was correct. to know if the password
// was correct, you'll have to match up the event information with
// the operation that triggered it.
virtual void userSubmitted(const QCA::SecureArray &password, const QCA::Event &event);
// called when a user-entered password is submitted. note that this
// does not mean the password was correct. to know if the password
// was correct, you'll have to match up the event information with
// the operation that triggered it.
virtual void userSubmitted(const QCA::SecureArray &password, const QCA::Event &event);
private:
class Private;
friend class Private;
Private *d;
class Private;
friend class Private;
Private *d;
};
#endif

View File

@ -1,7 +1,5 @@
set(eventhandlerdemo_bin_SRCS eventhandlerdemo.cpp)
MY_AUTOMOC( eventhandlerdemo_bin_SRCS)
add_executable(eventhandlerdemo ${eventhandlerdemo_bin_SRCS})
target_link_qca_libraries(eventhandlerdemo)

View File

@ -33,77 +33,77 @@
/**
We need a class on the client side to handle password requests.
*/
class ClientPassphraseHandler: public QObject
class ClientPassphraseHandler : public QObject
{
Q_OBJECT
public:
ClientPassphraseHandler(QObject *parent = 0) : QObject( parent )
ClientPassphraseHandler(QObject *parent = nullptr)
: QObject(parent)
{
// When the PasswordAsker or TokenAsker needs to interact
// with the user, it raises a signal. We connect that to a
// local slot to get the required information.
connect( &m_handler, SIGNAL( eventReady(int, const QCA::Event &) ),
SLOT( my_eventReady(int, const QCA::Event &) ) );
connect(&m_handler, &QCA::EventHandler::eventReady, this, &ClientPassphraseHandler::my_eventReady);
// Now that we are set up, we can start the EventHandler. Nothing
// will happen if you don't call this method.
m_handler.start();
}
private slots:
private Q_SLOTS:
// This slot gets called when the provider needs a token inserted,
// or to get a passphrase / password / PIN.
void my_eventReady(int id, const QCA::Event &event)
{
// We can sanity check the event
if ( event.isNull() ) {
if (event.isNull()) {
return;
}
// Events can be associated with a a keystore or a file/bytearray
// You can tell which by looking at the Source
if ( event.source() == QCA::Event::KeyStore ) {
if (event.source() == QCA::Event::KeyStore) {
std::cout << "Event is associated with a key store operation" << std::endl;
} else if ( event.source() == QCA::Event::Data ) {
} else if (event.source() == QCA::Event::Data) {
std::cout << "Event is associated with a file or some other data" << std::endl;
// if the event comes from a file type operation, you can get the
// name / label using fileName()
std::cout << " Filename: " << qPrintable( event.fileName() ) << std::endl;
std::cout << " Filename: " << qPrintable(event.fileName()) << std::endl;
} else {
std::cout << "Unexpected Source for Event" << std::endl;
}
// There are different kinds of events.
if ( event.type() == QCA::Event::Token ) {
if (event.type() == QCA::Event::Token) {
// You would typically ask the user to insert the token here
std::cout << "Request for token" << std::endl;
// we just fake it for this demo.
m_handler.tokenOkay( id );
m_handler.tokenOkay(id);
// you could use m_handler.reject( id ) to refuse the token request
} else if ( event.type() == QCA::Event::Password ) {
} else if (event.type() == QCA::Event::Password) {
std::cout << "Request for password, passphrase or PIN" << std::endl;
// and within the Password type, we have a few different styles.
if ( event.passwordStyle() == QCA::Event::StylePassword ) {
if (event.passwordStyle() == QCA::Event::StylePassword) {
std::cout << " [Password request]" << std::endl;
} else if ( event.passwordStyle() == QCA::Event::StylePassphrase ) {
} else if (event.passwordStyle() == QCA::Event::StylePassphrase) {
std::cout << " [Passphrase request]" << std::endl;
} else if ( event.passwordStyle() == QCA::Event::StylePIN ){
} else if (event.passwordStyle() == QCA::Event::StylePIN) {
std::cout << " [PIN request]" << std::endl;
} else {
std::cout << " [unexpect request style]" << std::endl;
}
// You would typically request the password/PIN/passphrase.
// again, we just fake it.
m_handler.submitPassword( id, QCA::SecureArray( "hello" ) );
m_handler.submitPassword(id, QCA::SecureArray("hello"));
} else {
std::cout << "Unexpected event type" << std::endl;
}
}
private:
QCA::EventHandler m_handler;
};
void asker_procedure();
@ -112,7 +112,7 @@ class AskerThread : public QThread
{
Q_OBJECT
protected:
virtual void run()
void run() override
{
asker_procedure();
}
@ -130,7 +130,7 @@ int main(int argc, char **argv)
// handler and asker cannot occur in the same thread
AskerThread askerThread;
QObject::connect(&askerThread, SIGNAL(finished()), &exampleApp, SLOT(quit()));
QObject::connect(&askerThread, &AskerThread::finished, &exampleApp, &QCoreApplication::quit);
askerThread.start();
exampleApp.exec();
@ -141,7 +141,7 @@ void asker_procedure()
{
QCA::PasswordAsker pwAsker;
pwAsker.ask( QCA::Event::StylePassword, "foo.tmp", 0 );
pwAsker.ask(QCA::Event::StylePassword, QStringLiteral("foo.tmp"), nullptr);
pwAsker.waitForResponse();
@ -151,11 +151,14 @@ void asker_procedure()
QCA::TokenAsker tokenAsker;
tokenAsker.ask( QCA::KeyStoreInfo( QCA::KeyStore::SmartCard, "Token Id", "Token Name" ), QCA::KeyStoreEntry(), 0 );
tokenAsker.ask(
QCA::KeyStoreInfo(QCA::KeyStore::SmartCard, QStringLiteral("Token Id"), QStringLiteral("Token Name")),
QCA::KeyStoreEntry(),
nullptr);
tokenAsker.waitForResponse();
if ( tokenAsker.accepted() ) {
if (tokenAsker.accepted()) {
std::cout << "Token was accepted" << std::endl;
} else {
std::cout << "Token was not accepted" << std::endl;

View File

@ -169,7 +169,7 @@ The code below shows how to create an SSL client
*/
/* \example tlssocket.cpp
/** \example tlssocket.cpp
The code below shows how to create a socket that can operate
over an Transport Layer Security (TLS, also known as SSL) connection.

View File

@ -24,7 +24,7 @@
#include <QCoreApplication>
#include <stdio.h>
#include <cstdio>
#ifdef QT_STATICPLUGIN
#include "import_plugins.h"
@ -32,47 +32,46 @@
int main(int argc, char **argv)
{
// the Initializer object sets things up, and
// also does cleanup when it goes out of scope
QCA::Initializer init;
// the Initializer object sets things up, and
// also does cleanup when it goes out of scope
QCA::Initializer init;
QCoreApplication app(argc, argv);
QCoreApplication app(argc, argv);
// we use the first argument if provided, or
// use "hello" if no arguments
QCA::SecureArray arg = (argc >= 2) ? argv[1] : "hello";
// we use the first argument if provided, or
// use "hello" if no arguments
QCA::SecureArray arg = (argc >= 2) ? argv[1] : "hello";
// must always check that an algorithm is supported before using it
if( !QCA::isSupported("sha1") )
printf("SHA1 not supported!\n");
else {
// this shows the "all in one" approach
QString result = QCA::Hash("sha1").hashToString(arg);
printf("sha1(\"%s\") = [%s]\n", arg.data(), qPrintable(result));
}
// must always check that an algorithm is supported before using it
if (!QCA::isSupported("sha1"))
printf("SHA1 not supported!\n");
else {
// this shows the "all in one" approach
QString result = QCA::Hash(QStringLiteral("sha1")).hashToString(arg);
printf("sha1(\"%s\") = [%s]\n", arg.data(), qPrintable(result));
}
// must always check that an algorithm is supported before using it
if( !QCA::isSupported("md5") )
printf("MD5 not supported!\n");
else {
// this shows the incremental approach. Naturally
// for this simple job, we could use the "all in one"
// approach - this is an example, after all :-)
QCA::SecureArray part1(arg.toByteArray().left(3)); // three chars - "hel"
QCA::SecureArray part2(arg.toByteArray().mid(3)); // the rest - "lo"
// must always check that an algorithm is supported before using it
if (!QCA::isSupported("md5"))
printf("MD5 not supported!\n");
else {
// this shows the incremental approach. Naturally
// for this simple job, we could use the "all in one"
// approach - this is an example, after all :-)
QCA::SecureArray part1(arg.toByteArray().left(3)); // three chars - "hel"
QCA::SecureArray part2(arg.toByteArray().mid(3)); // the rest - "lo"
// create the required object.
QCA::Hash hashObject("md5");
// we split it into two parts to show incremental update
hashObject.update(part1);
hashObject.update(part2);
// no more updates after calling final.
QCA::SecureArray resultArray = hashObject.final();
// convert the result into printable hexadecimal.
QString result = QCA::arrayToHex(resultArray.toByteArray());
printf("md5(\"%s\") = [%s]\n", arg.data(), qPrintable(result));
}
// create the required object.
QCA::Hash hashObject(QStringLiteral("md5"));
// we split it into two parts to show incremental update
hashObject.update(part1);
hashObject.update(part2);
// no more updates after calling final.
QCA::SecureArray resultArray = hashObject.final();
// convert the result into printable hexadecimal.
QString result = QCA::arrayToHex(resultArray.toByteArray());
printf("md5(\"%s\") = [%s]\n", arg.data(), qPrintable(result));
}
return 0;
return 0;
}

View File

@ -32,39 +32,38 @@
int main(int argc, char **argv)
{
// the Initializer object sets things up, and
// also does cleanup when it goes out of scope
QCA::Initializer init;
// the Initializer object sets things up, and
// also does cleanup when it goes out of scope
QCA::Initializer init;
QCoreApplication app(argc, argv);
QCoreApplication app(argc, argv);
// we use the first argument as the data to encode / decode
// if an argument is provided. Use "hello" if no argument
QByteArray arg; // empty array
arg.append((argc >= 2) ? argv[1] : "hello");
// we use the first argument as the data to encode / decode
// if an argument is provided. Use "hello" if no argument
QByteArray arg; // empty array
arg.append((argc >= 2) ? argv[1] : "hello");
// create our object, which does encoding by default
// QCA::Hex encoder(QCA::Encode); is equivalent
QCA::Hex encoder;
// create our object, which does encoding by default
// QCA::Hex encoder(QCA::Encode); is equivalent
QCA::Hex encoder;
// You might prefer to use encoder.encode(); and have
// it return a QCA::SecureArray, depending on your needs
QString encoded = encoder.arrayToString(arg);
// You might prefer to use encoder.encode(); and have
// it return a QCA::SecureArray, depending on your needs
QString encoded = encoder.arrayToString(arg);
std::cout << arg.data() << " in hex encoding is ";
std::cout << encoded.toLatin1().data() << std::endl;
std::cout << arg.data() << " in hex encoding is ";
std::cout << encoded.toLatin1().data() << std::endl;
// This time, we'll create an object to decode hexadecimal.
// We could also have reused the existing object, calling
// clear(); and setup(QCA::Decode); on it.
QCA::Hex decoder(QCA::Decode);
// This time, we'll create an object to decode hexadecimal.
// We could also have reused the existing object, calling
// clear(); and setup(QCA::Decode); on it.
QCA::Hex decoder(QCA::Decode);
// This time, we convert a QString into a QString
QString decoded = decoder.decodeString(encoded);
// This time, we convert a QString into a QString
QString decoded = decoder.decodeString(encoded);
std::cout << encoded.toLatin1().data() << " decoded from hex is ";
std::cout << decoded.toLatin1().data() << std::endl;
std::cout << encoded.toLatin1().data() << " decoded from hex is ";
std::cout << decoded.toLatin1().data() << std::endl;
return 0;
return 0;
}

View File

@ -1,7 +1,5 @@
set(keyloader_bin_SRCS keyloader.cpp)
MY_AUTOMOC( keyloader_bin_SRCS )
add_executable(keyloader ${keyloader_bin_SRCS})
target_link_qca_libraries(keyloader)

View File

@ -23,98 +23,94 @@
#include <QtCrypto>
#include <QCoreApplication>
#include <QFile>
#include <QTimer>
#include <stdio.h>
#include <cstdio>
#ifdef QT_STATICPLUGIN
#include "import_plugins.h"
#endif
class PassphraseHandler: public QObject
class PassphraseHandler : public QObject
{
Q_OBJECT
Q_OBJECT
public:
QCA::EventHandler handler;
QCA::EventHandler handler;
PassphraseHandler(QObject *parent = 0) : QObject(parent)
{
connect(&handler, SIGNAL(eventReady(int, const QCA::Event &)),
SLOT(eh_eventReady(int, const QCA::Event &)));
handler.start();
}
PassphraseHandler(QObject *parent = nullptr)
: QObject(parent)
{
connect(&handler, &QCA::EventHandler::eventReady, this, &PassphraseHandler::eh_eventReady);
handler.start();
}
private slots:
void eh_eventReady(int id, const QCA::Event &event)
{
if(event.type() == QCA::Event::Password)
{
QCA::SecureArray pass;
QCA::ConsolePrompt prompt;
prompt.getHidden("Passphrase");
prompt.waitForFinished();
pass = prompt.result();
handler.submitPassword(id, pass);
}
else
handler.reject(id);
}
private Q_SLOTS:
void eh_eventReady(int id, const QCA::Event &event)
{
if (event.type() == QCA::Event::Password) {
QCA::SecureArray pass;
QCA::ConsolePrompt prompt;
prompt.getHidden(QStringLiteral("Passphrase"));
prompt.waitForFinished();
pass = prompt.result();
handler.submitPassword(id, pass);
} else
handler.reject(id);
}
};
class App : public QObject
{
Q_OBJECT
Q_OBJECT
public:
QCA::KeyLoader keyLoader;
QString str;
QCA::KeyLoader keyLoader;
QString str;
App()
{
connect(&keyLoader, SIGNAL(finished()), SLOT(kl_finished()));
}
App()
{
connect(&keyLoader, &QCA::KeyLoader::finished, this, &App::kl_finished);
}
public slots:
void start()
{
keyLoader.loadPrivateKeyFromPEMFile(str);
}
public Q_SLOTS:
void start()
{
keyLoader.loadPrivateKeyFromPEMFile(str);
}
signals:
void quit();
Q_SIGNALS:
void quit();
private slots:
void kl_finished()
{
if(keyLoader.convertResult() == QCA::ConvertGood)
{
QCA::PrivateKey key = keyLoader.privateKey();
printf("Loaded successfully. Bits: %d\n", key.bitSize());
}
else
printf("Unable to load.\n");
private Q_SLOTS:
void kl_finished()
{
if (keyLoader.convertResult() == QCA::ConvertGood) {
QCA::PrivateKey key = keyLoader.privateKey();
printf("Loaded successfully. Bits: %d\n", key.bitSize());
} else
printf("Unable to load.\n");
emit quit();
}
emit quit();
}
};
int main(int argc, char **argv)
{
QCA::Initializer init;
QCoreApplication qapp(argc, argv);
QCA::Initializer init;
QCoreApplication qapp(argc, argv);
if(argc < 2)
{
printf("usage: keyloader [privatekey.pem]\n");
return 0;
}
if (argc < 2) {
printf("usage: keyloader [privatekey.pem]\n");
return 0;
}
PassphraseHandler passphraseHandler;
App app;
app.str = argv[1];
QObject::connect(&app, SIGNAL(quit()), &qapp, SLOT(quit()));
QTimer::singleShot(0, &app, SLOT(start()));
qapp.exec();
return 0;
PassphraseHandler passphraseHandler;
App app;
app.str = QFile::decodeName(argv[1]);
QObject::connect(&app, &App::quit, &qapp, QCoreApplication::quit);
QTimer::singleShot(0, &app, &App::start);
qapp.exec();
return 0;
}
#include "keyloader.moc"

View File

@ -26,7 +26,7 @@
#include <QDebug>
// needed for printf
#include<stdio.h>
#include <cstdio>
#ifdef QT_STATICPLUGIN
#include "import_plugins.h"
@ -34,53 +34,52 @@
int main(int argc, char **argv)
{
// the Initializer object sets things up, and
// also does cleanup when it goes out of scope
QCA::Initializer init;
// the Initializer object sets things up, and
// also does cleanup when it goes out of scope
QCA::Initializer init;
QCoreApplication app(argc, argv);
QCoreApplication app(argc, argv);
qDebug() << "This example shows hashed MAC";
qDebug() << "This example shows hashed MAC";
// we use the first argument as the data to authenticate
// if an argument is provided. Use "hello" if no argument
QByteArray arg = (argc >= 2) ? argv[1] : "hello";
// we use the first argument as the data to authenticate
// if an argument is provided. Use "hello" if no argument
QByteArray arg = (argc >= 2) ? argv[1] : "hello";
// we use the second argument as the key to authenticate
// with, if two arguments are provided. Use "secret" as
// the key if less than two arguments.
QCA::SecureArray key((argc >= 3) ? argv[2] : "secret");
// we use the second argument as the key to authenticate
// with, if two arguments are provided. Use "secret" as
// the key if less than two arguments.
QCA::SecureArray key((argc >= 3) ? argv[2] : "secret");
// must always check that an algorithm is supported before using it
if( !QCA::isSupported("hmac(sha1)") ) {
printf("HMAC(SHA1) not supported!\n");
} else {
// create the required object using HMAC with SHA-1, and an
// empty key.
QCA::MessageAuthenticationCode hmacObject( "hmac(sha1)", QCA::SecureArray() );
// must always check that an algorithm is supported before using it
if (!QCA::isSupported("hmac(sha1)")) {
printf("HMAC(SHA1) not supported!\n");
} else {
// create the required object using HMAC with SHA-1, and an
// empty key.
QCA::MessageAuthenticationCode hmacObject(QStringLiteral("hmac(sha1)"), QCA::SecureArray());
// create the key
QCA::SymmetricKey keyObject(key);
// create the key
QCA::SymmetricKey keyObject(key);
// set the HMAC object to use the key
hmacObject.setup(key);
// that could also have been done in the
// QCA::MessageAuthenticationCode constructor
// set the HMAC object to use the key
hmacObject.setup(key);
// that could also have been done in the
// QCA::MessageAuthenticationCode constructor
// we split it into two parts to show incremental update
QCA::SecureArray part1(arg.left(3)); // three chars - "hel"
QCA::SecureArray part2(arg.mid(3)); // the rest - "lo"
hmacObject.update(part1);
hmacObject.update(part2);
// we split it into two parts to show incremental update
QCA::SecureArray part1(arg.left(3)); // three chars - "hel"
QCA::SecureArray part2(arg.mid(3)); // the rest - "lo"
hmacObject.update(part1);
hmacObject.update(part2);
// no more updates after calling final.
QCA::SecureArray resultArray = hmacObject.final();
// no more updates after calling final.
QCA::SecureArray resultArray = hmacObject.final();
// convert the result into printable hexadecimal.
QString result = QCA::arrayToHex(resultArray.toByteArray());
printf("HMAC(SHA1) of \"%s\" with \"%s\" = [%s]\n", arg.data(), key.data(), result.toLatin1().data());
}
// convert the result into printable hexadecimal.
QString result = QCA::arrayToHex(resultArray.toByteArray());
printf("HMAC(SHA1) of \"%s\" with \"%s\" = [%s]\n", arg.data(), key.data(), result.toLatin1().data());
}
return 0;
return 0;
}

View File

@ -25,118 +25,97 @@
(http://www-128.ibm.com/developerworks/linux/library/l-md5crypt/)
*/
#include <QtCrypto>
#include <QCoreApplication>
#include <QtCrypto>
#include <QtDebug>
#include <stdio.h>
#include <cstdio>
#ifdef QT_STATICPLUGIN
#include "import_plugins.h"
#endif
QString to64 ( long v , int size )
QString to64(long v, int size)
{
// Character set of the encrypted password: A-Za-z0-9./
QString itoa64 = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
QString itoa64 = QStringLiteral("./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz");
QString result;
while ( --size >= 0 )
{
result.append ( itoa64.at ( ( int )( v & 0x3f ) ) );
while (--size >= 0) {
result.append(itoa64.at((int)(v & 0x3f)));
v = v >> 6;
}
return result;
}
int byte2unsigned ( int byteValue )
int byte2unsigned(int byteValue)
{
int integerToReturn;
integerToReturn = (int) byteValue & 0xff;
integerToReturn = (int)byteValue & 0xff;
return integerToReturn;
}
QString qca_md5crypt( const QCA::SecureArray &password, const QCA::SecureArray &salt )
QString qca_md5crypt(const QCA::SecureArray &password, const QCA::SecureArray &salt)
{
QCA::SecureArray finalState, magic_string = "$1$";
// The md5crypt algorithm uses two separate hashes
QCA::Hash hash1( "md5" );
QCA::Hash hash2( "md5" );
QCA::Hash hash1(QStringLiteral("md5"));
QCA::Hash hash2(QStringLiteral("md5"));
// MD5 Hash #1: pwd, magic string and salt
hash1.update ( password );
hash1.update ( magic_string );
hash1.update ( salt );
hash1.update(password);
hash1.update(magic_string);
hash1.update(salt);
// MD5 Hash #2: password, salt, password
hash2.update ( password );
hash2.update ( salt );
hash2.update ( password );
hash2.update(password);
hash2.update(salt);
hash2.update(password);
finalState = hash2.final();
// Two sets of transformations based on the length of the password
for ( int i = password.size() ; i > 0 ; i -= 16 )
{
for (int i = password.size(); i > 0; i -= 16) {
// Update hash1 from offset value (i > 16 ? 16 : i)
hash1.update( finalState.toByteArray().left(i > 16 ? 16 : i));
hash1.update(finalState.toByteArray().left(i > 16 ? 16 : i));
}
// Clear array bits
finalState.fill( 0 );
finalState.fill(0);
for ( int i = password.size() ; i != 0 ; i = i >> 1 )
{
if ( ( i & 1 ) != 0 )
{
hash1.update( finalState.toByteArray().left ( 1 ) );
}
else
{
hash1.update( password.toByteArray().left ( 1 ) );
for (int i = password.size(); i != 0; i = i >> 1) {
if ((i & 1) != 0) {
hash1.update(finalState.toByteArray().left(1));
} else {
hash1.update(password.toByteArray().left(1));
}
}
finalState = hash1.final();
// Now build a 1000 entry dictionary...
for ( int i = 0 ; i < 1000 ; i++ )
{
for (int i = 0; i < 1000; i++) {
hash2.clear();
if ((i & 1) != 0)
{
hash2.update ( password );
}
else
{
hash2.update ( finalState.toByteArray().left( 16 ));
if ((i & 1) != 0) {
hash2.update(password);
} else {
hash2.update(finalState.toByteArray().left(16));
}
if ((i % 3) != 0)
{
hash2.update ( salt );
if ((i % 3) != 0) {
hash2.update(salt);
}
if ((i % 7) != 0)
{
hash2.update ( password );
if ((i % 7) != 0) {
hash2.update(password);
}
if ((i & 1) != 0)
{
hash2.update ( finalState.toByteArray().left( 16 ) );
}
else
{
hash2.update ( password );
if ((i & 1) != 0) {
hash2.update(finalState.toByteArray().left(16));
} else {
hash2.update(password);
}
finalState = hash2.final();
@ -146,80 +125,69 @@ QString qca_md5crypt( const QCA::SecureArray &password, const QCA::SecureArray &
// Salt is part of the encoded password ($1$<string>$)
QString encodedString;
encodedString.append ( magic_string.toByteArray() );
encodedString.append ( salt.toByteArray() );
encodedString.append ( "$" );
encodedString.append(QString::fromLatin1(magic_string.toByteArray()));
encodedString.append(QString::fromLatin1(salt.toByteArray()));
encodedString.append(QStringLiteral("$"));
long l;
l = ( byte2unsigned (finalState.toByteArray().at(0) ) << 16 |
( byte2unsigned (finalState.toByteArray().at(6)) ) << 8 |
byte2unsigned (finalState.toByteArray().at(12)) );
encodedString.append ( to64 (l, 4) );
l = (byte2unsigned(finalState.toByteArray().at(0)) << 16 | (byte2unsigned(finalState.toByteArray().at(6))) << 8 |
byte2unsigned(finalState.toByteArray().at(12)));
encodedString.append(to64(l, 4));
l = ( byte2unsigned (finalState.toByteArray().at(1)) << 16 |
( byte2unsigned (finalState.toByteArray().at(7))) << 8 |
byte2unsigned (finalState.toByteArray().at(13)) );
encodedString.append ( to64 (l, 4) );
l = (byte2unsigned(finalState.toByteArray().at(1)) << 16 | (byte2unsigned(finalState.toByteArray().at(7))) << 8 |
byte2unsigned(finalState.toByteArray().at(13)));
encodedString.append(to64(l, 4));
l = ( byte2unsigned (finalState.toByteArray().at(2)) << 16 |
( byte2unsigned (finalState.toByteArray().at(8))) << 8 |
byte2unsigned (finalState.toByteArray().at(14)) );
encodedString.append ( to64 (l, 4) );
l = (byte2unsigned(finalState.toByteArray().at(2)) << 16 | (byte2unsigned(finalState.toByteArray().at(8))) << 8 |
byte2unsigned(finalState.toByteArray().at(14)));
encodedString.append(to64(l, 4));
l = ( byte2unsigned (finalState.toByteArray().at(3)) << 16 |
( byte2unsigned (finalState.toByteArray().at(9))) << 8 |
byte2unsigned (finalState.toByteArray().at(15)) );
encodedString.append ( to64 (l, 4) );
l = (byte2unsigned(finalState.toByteArray().at(3)) << 16 | (byte2unsigned(finalState.toByteArray().at(9))) << 8 |
byte2unsigned(finalState.toByteArray().at(15)));
encodedString.append(to64(l, 4));
l = ( byte2unsigned (finalState.toByteArray().at(4)) << 16 |
( byte2unsigned (finalState.toByteArray().at(10))) << 8 |
byte2unsigned (finalState.toByteArray().at(5)) );
encodedString.append ( to64 (l, 4) );
l = (byte2unsigned(finalState.toByteArray().at(4)) << 16 | (byte2unsigned(finalState.toByteArray().at(10))) << 8 |
byte2unsigned(finalState.toByteArray().at(5)));
encodedString.append(to64(l, 4));
l = byte2unsigned (finalState.toByteArray().at(11));
encodedString.append ( to64 (l, 2) );
l = byte2unsigned(finalState.toByteArray().at(11));
encodedString.append(to64(l, 2));
return encodedString;
}
int main(int argc, char **argv)
{
// the Initializer object sets things up, and
// also does cleanup when it goes out of scope
QCA::Initializer init;
QCoreApplication app ( argc, argv );
QCoreApplication app(argc, argv);
QCA::SecureArray password, salt;
if ( argc < 3 )
{
printf ( "Usage: %s password salt (salt without $1$)\n" , argv[0] );
if (argc < 3) {
printf("Usage: %s password salt (salt without $1$)\n", argv[0]);
return 1;
}
password.append( argv[1] );
password.append(argv[1]);
salt.append( argv[2] );
salt.append(argv[2]);
// must always check that an algorithm is supported before using it
if( !QCA::isSupported( "md5" ) )
printf ("MD5 hash not supported!\n");
else
{
QString result = qca_md5crypt( password, salt );
if (!QCA::isSupported("md5"))
printf("MD5 hash not supported!\n");
else {
QString result = qca_md5crypt(password, salt);
printf ("md5crypt [ %s , %s ] = '%s'\n" , password.data(), salt.data() , qPrintable(result) );
printf("md5crypt [ %s , %s ] = '%s'\n", password.data(), salt.data(), qPrintable(result));
// this is equivalent if you have GNU libc 2.0
// printf( "GNU md5crypt [ %s , %s ] = '%s'\n", password.data(), salt.data(), crypt( password.data(), ( "$1$"+salt ).data() ) );
// printf( "GNU md5crypt [ %s , %s ] = '%s'\n", password.data(), salt.data(), crypt( password.data(), (
// "$1$"+salt ).data() ) );
}
return 0;
}

View File

@ -20,8 +20,8 @@
*/
// QtCrypto has the declarations for all of QCA
#include <QtCrypto>
#include <QCoreApplication>
#include <QtCrypto>
#include <iostream>
#include <qstringlist.h>
@ -44,15 +44,15 @@ int main(int argc, char **argv)
QCA::scanForPlugins();
// this gives us all the plugin providers as a list
QCA::ProviderList qcaProviders = QCA::providers();
for (int i = 0; i < qcaProviders.size(); ++i) {
// each provider has a name, which we can display
std::cout << qcaProviders[i]->name().toLatin1().data() << ": ";
// ... and also a list of features
QStringList capabilities = qcaProviders[i]->features();
// we turn the string list back into a single string,
// and display it as well
std::cout << capabilities.join(", ").toLatin1().data() << std::endl;
const QCA::ProviderList qcaProviders = QCA::providers();
for (const QCA::Provider *provider : qcaProviders) {
// each provider has a name, which we can display
std::cout << provider->name().toLatin1().data() << ": ";
// ... and also a list of features
QStringList capabilities = provider->features();
// we turn the string list back into a single string,
// and display it as well
std::cout << capabilities.join(QStringLiteral(", ")).toLatin1().data() << std::endl;
}
// Note that the default provider isn't included in
@ -61,7 +61,6 @@ int main(int argc, char **argv)
// However it is still possible to get the features
// supported by the default provider
QStringList capabilities = QCA::defaultFeatures();
std::cout << capabilities.join(", ").toLatin1().data() << std::endl;
std::cout << capabilities.join(QStringLiteral(", ")).toLatin1().data() << std::endl;
return 0;
}

View File

@ -20,7 +20,6 @@
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <QtCrypto>
#include <QCoreApplication>
@ -31,7 +30,7 @@
#include "import_plugins.h"
#endif
int main(int argc, char** argv)
int main(int argc, char **argv)
{
// the Initializer object sets things up, and
// also does cleanup when it goes out of scope
@ -40,37 +39,37 @@ int main(int argc, char** argv)
QCoreApplication app(argc, argv);
// We need to ensure that we have certificate handling support
if ( !QCA::isSupported( "cert" ) ) {
std::cout << "Sorry, no PKI certificate support" << std::endl;
return 1;
if (!QCA::isSupported("cert")) {
std::cout << "Sorry, no PKI certificate support" << std::endl;
return 1;
}
// Read in a private key
QCA::PrivateKey privKey;
QCA::PrivateKey privKey;
QCA::ConvertResult convRes;
QCA::SecureArray passPhrase = "start";
privKey = QCA::PrivateKey::fromPEMFile( "Userkey.pem", passPhrase, &convRes );
if ( convRes != QCA::ConvertGood ) {
std::cout << "Sorry, could not import Private Key" << std::endl;
return 1;
QCA::SecureArray passPhrase = "start";
privKey = QCA::PrivateKey::fromPEMFile(QStringLiteral("Userkey.pem"), passPhrase, &convRes);
if (convRes != QCA::ConvertGood) {
std::cout << "Sorry, could not import Private Key" << std::endl;
return 1;
}
// Read in a matching public key cert
// you could also build this using the fromPEMFile() method
QCA::Certificate pubCert( "User.pem" );
if ( pubCert.isNull() ) {
std::cout << "Sorry, could not import public key certificate" << std::endl;
return 1;
QCA::Certificate pubCert(QStringLiteral("User.pem"));
if (pubCert.isNull()) {
std::cout << "Sorry, could not import public key certificate" << std::endl;
return 1;
}
// We are building the certificate into a SecureMessageKey object, via a
// CertificateChain
QCA::SecureMessageKey secMsgKey;
QCA::CertificateChain chain;
chain += pubCert;
secMsgKey.setX509CertificateChain( chain );
secMsgKey.setX509CertificateChain(chain);
// build up a SecureMessage object, based on our public key certificate
QCA::CMS cms;
QCA::CMS cms;
QCA::SecureMessage msg(&cms);
msg.setRecipient(secMsgKey);
@ -85,33 +84,31 @@ int main(int argc, char** argv)
msg.waitForFinished(1000);
// check to see if it worked
if(!msg.success())
{
std::cout << "Error encrypting: " << msg.errorCode() << std::endl;
return 1;
if (!msg.success()) {
std::cout << "Error encrypting: " << msg.errorCode() << std::endl;
return 1;
}
// get the result
QCA::SecureArray cipherText = msg.read();
QCA::Base64 enc;
QCA::Base64 enc;
std::cout << plainText.data() << " encrypts to (in base 64): ";
std::cout << qPrintable( enc.arrayToString( cipherText ) ) << std::endl;
std::cout << qPrintable(enc.arrayToString(cipherText)) << std::endl;
// Show we can decrypt it with the private key
if ( !privKey.canDecrypt() ) {
std::cout << "Private key cannot be used to decrypt" << std::endl;
return 1;
if (!privKey.canDecrypt()) {
std::cout << "Private key cannot be used to decrypt" << std::endl;
return 1;
}
QCA::SecureArray plainTextResult;
if ( 0 == privKey.decrypt(cipherText, &plainTextResult, QCA::EME_PKCS1_OAEP ) ) {
std::cout << "Decryption process failed" << std::endl;
return 1;
if (0 == privKey.decrypt(cipherText, &plainTextResult, QCA::EME_PKCS1_OAEP)) {
std::cout << "Decryption process failed" << std::endl;
return 1;
}
std::cout << qPrintable( enc.arrayToString( cipherText ) );
std::cout << qPrintable(enc.arrayToString(cipherText));
std::cout << " (in base 64) decrypts to: ";
std::cout << plainTextResult.data() << std::endl;
return 0;
}

View File

@ -33,41 +33,40 @@
int main(int argc, char **argv)
{
// the Initializer object sets things up, and
// also does cleanup when it goes out of scope
QCA::Initializer init;
// the Initializer object sets things up, and
// also does cleanup when it goes out of scope
QCA::Initializer init;
QCoreApplication app(argc, argv);
QCoreApplication app(argc, argv);
qDebug() << "This example generates random numbers";
qDebug() << "This example generates random numbers";
int randInt;
// This is the standard way to generate a random integer.
randInt = QCA::Random::randomInt();
qDebug() << "A random number: " << randInt;
int randInt;
// This is the standard way to generate a random integer.
randInt = QCA::Random::randomInt();
qDebug() << "A random number: " << randInt;
// If you wanted a random character (octet), you could
// use something like:
unsigned char randChar;
randChar = QCA::Random::randomChar();
// It might not be printable, so this may not produce output
std::cout << "A random character: " << randChar << std::endl;
// If you wanted a random character (octet), you could
// use something like:
unsigned char randChar;
randChar = QCA::Random::randomChar();
// It might not be printable, so this may not produce output
std::cout << "A random character: " << randChar << std::endl;
QCA::SecureArray tenBytes(10);
// If you need more random values, you may want to
// get an array, as shown below.
tenBytes = QCA::Random::randomArray(10);
QCA::SecureArray tenBytes(10);
// If you need more random values, you may want to
// get an array, as shown below.
tenBytes = QCA::Random::randomArray(10);
// To make this viewable, we convert to hexadecimal.
std::cout << "A random 10 byte array (in hex): ";
std::cout << qPrintable(QCA::Hex().arrayToString(tenBytes)) << std::endl;
// To make this viewable, we convert to hexadecimal.
std::cout << "A random 10 byte array (in hex): ";
std::cout << qPrintable(QCA::Hex().arrayToString(tenBytes)) << std::endl;
// Under some circumstances, you may want to create a
// Random object, rather than a static public member function.
// This isn't normally the easiest way, but it does work
QCA::Random myRandomObject;
randChar = myRandomObject.nextByte();
tenBytes = myRandomObject.nextBytes(10);
return 0;
// Under some circumstances, you may want to create a
// Random object, rather than a static public member function.
// This isn't normally the easiest way, but it does work
QCA::Random myRandomObject;
randChar = myRandomObject.nextByte();
tenBytes = myRandomObject.nextBytes(10);
return 0;
}

View File

@ -20,8 +20,8 @@
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <QtCrypto>
#include <QCoreApplication>
#include <QtCrypto>
#include <iostream>
@ -43,115 +43,109 @@ int main(int argc, char **argv)
// We demonstrate PEM usage here, so we need to test for
// supportedIOTypes, not just supportedTypes
if(!QCA::isSupported("pkey") ||
!QCA::PKey::supportedIOTypes().contains(QCA::PKey::RSA))
std::cout << "RSA not supported!\n";
if (!QCA::isSupported("pkey") || !QCA::PKey::supportedIOTypes().contains(QCA::PKey::RSA))
std::cout << "RSA not supported!\n";
else {
// When creating a public / private key pair, you make the
// private key, and then extract the public key component from it
// Using RSA is very common, however DSA can provide equivalent
// signature/verification. This example applies to DSA to the
// extent that the operations work on that key type.
// When creating a public / private key pair, you make the
// private key, and then extract the public key component from it
// Using RSA is very common, however DSA can provide equivalent
// signature/verification. This example applies to DSA to the
// extent that the operations work on that key type.
// QCA provides KeyGenerator as a convenient source of new keys,
// however you could also import an existing key instead.
QCA::PrivateKey seckey = QCA::KeyGenerator().createRSA(1024);
if(seckey.isNull()) {
std::cout << "Failed to make private RSA key" << std::endl;
return 1;
}
// QCA provides KeyGenerator as a convenient source of new keys,
// however you could also import an existing key instead.
QCA::PrivateKey seckey = QCA::KeyGenerator().createRSA(1024);
if (seckey.isNull()) {
std::cout << "Failed to make private RSA key" << std::endl;
return 1;
}
QCA::PublicKey pubkey = seckey.toPublicKey();
QCA::PublicKey pubkey = seckey.toPublicKey();
// check if the key can encrypt
if(!pubkey.canEncrypt()) {
std::cout << "Error: this kind of key cannot encrypt" << std::endl;
return 1;
}
// check if the key can encrypt
if (!pubkey.canEncrypt()) {
std::cout << "Error: this kind of key cannot encrypt" << std::endl;
return 1;
}
// encrypt some data - note that only the public key is required
// you must also choose the algorithm to be used
QCA::SecureArray result = pubkey.encrypt(arg, QCA::EME_PKCS1_OAEP);
if(result.isEmpty()) {
std::cout << "Error encrypting" << std::endl;
return 1;
}
// encrypt some data - note that only the public key is required
// you must also choose the algorithm to be used
QCA::SecureArray result = pubkey.encrypt(arg, QCA::EME_PKCS1_OAEP);
if (result.isEmpty()) {
std::cout << "Error encrypting" << std::endl;
return 1;
}
// output the encrypted data
QString rstr = QCA::arrayToHex(result.toByteArray());
std::cout << "\"" << arg.data() << "\" encrypted with RSA is \"";
std::cout << qPrintable(rstr) << "\"" << std::endl;
// output the encrypted data
QString rstr = QCA::arrayToHex(result.toByteArray());
std::cout << "\"" << arg.data() << "\" encrypted with RSA is \"";
std::cout << qPrintable(rstr) << "\"" << std::endl;
// save the private key - in a real example, make sure this goes
// somewhere secure and has a good pass phrase
// You can use the same technique with the public key too.
QCA::SecureArray passPhrase = "pass phrase";
seckey.toPEMFile("keyprivate.pem", passPhrase);
// save the private key - in a real example, make sure this goes
// somewhere secure and has a good pass phrase
// You can use the same technique with the public key too.
QCA::SecureArray passPhrase = "pass phrase";
seckey.toPEMFile(QStringLiteral("keyprivate.pem"), passPhrase);
// Read that key back in, checking if the read succeeded
QCA::ConvertResult conversionResult;
QCA::PrivateKey privateKey = QCA::PrivateKey::fromPEMFile( "keyprivate.pem",
passPhrase,
&conversionResult);
if (! (QCA::ConvertGood == conversionResult) ) {
std::cout << "Private key read failed" << std::endl;
}
// Read that key back in, checking if the read succeeded
QCA::ConvertResult conversionResult;
QCA::PrivateKey privateKey =
QCA::PrivateKey::fromPEMFile(QStringLiteral("keyprivate.pem"), passPhrase, &conversionResult);
if (!(QCA::ConvertGood == conversionResult)) {
std::cout << "Private key read failed" << std::endl;
}
// now decrypt that encrypted data using the private key that
// we read in. The algorithm is the same.
QCA::SecureArray decrypt;
if(0 == privateKey.decrypt(result, &decrypt, QCA::EME_PKCS1_OAEP)) {
std::cout << "Error decrypting.\n";
return 1;
}
// now decrypt that encrypted data using the private key that
// we read in. The algorithm is the same.
QCA::SecureArray decrypt;
if (0 == privateKey.decrypt(result, &decrypt, QCA::EME_PKCS1_OAEP)) {
std::cout << "Error decrypting.\n";
return 1;
}
// output the resulting decrypted string
std::cout << "\"" << qPrintable(rstr) << "\" decrypted with RSA is \"";
std::cout << decrypt.data() << "\"" << std::endl;
// output the resulting decrypted string
std::cout << "\"" << qPrintable(rstr) << "\" decrypted with RSA is \"";
std::cout << decrypt.data() << "\"" << std::endl;
// Some private keys can also be used for producing signatures
if (!privateKey.canSign()) {
std::cout << "Error: this kind of key cannot sign" << std::endl;
return 1;
}
privateKey.startSign(QCA::EMSA3_MD5);
privateKey.update(arg); // just reuse the same message
QByteArray argSig = privateKey.signature();
// Some private keys can also be used for producing signatures
if(!privateKey.canSign()) {
std::cout << "Error: this kind of key cannot sign" << std::endl;
return 1;
}
privateKey.startSign( QCA::EMSA3_MD5 );
privateKey.update( arg ); // just reuse the same message
QByteArray argSig = privateKey.signature();
// instead of using the startSign(), update(), signature() calls,
// you may be better doing the whole thing in one go, using the
// signMessage call. Of course you need the whole message in one
// hit, which may or may not be a problem
// instead of using the startSign(), update(), signature() calls,
// you may be better doing the whole thing in one go, using the
// signMessage call. Of course you need the whole message in one
// hit, which may or may not be a problem
// output the resulting signature
rstr = QCA::arrayToHex(argSig);
std::cout << "Signature for \"" << arg.data() << "\" using RSA, is ";
std::cout << "\"" << qPrintable(rstr) << "\"" << std::endl;
// output the resulting signature
rstr = QCA::arrayToHex(argSig);
std::cout << "Signature for \"" << arg.data() << "\" using RSA, is ";
std::cout << "\"" << qPrintable( rstr ) << "\"" << std::endl;
// to check a signature, we must check that the key is
// appropriate
if(pubkey.canVerify()) {
pubkey.startVerify( QCA::EMSA3_MD5 );
pubkey.update( arg );
if ( pubkey.validSignature( argSig ) ) {
std::cout << "Signature is valid" << std::endl;
} else {
std::cout << "Bad signature" << std::endl;
}
}
// We can also do the verification in a single step if we
// have all the message
if ( pubkey.canVerify() &&
pubkey.verifyMessage( arg, argSig, QCA::EMSA3_MD5 ) ) {
std::cout << "Signature is valid" << std::endl;
} else {
std::cout << "Signature could not be verified" << std::endl;
}
// to check a signature, we must check that the key is
// appropriate
if (pubkey.canVerify()) {
pubkey.startVerify(QCA::EMSA3_MD5);
pubkey.update(arg);
if (pubkey.validSignature(argSig)) {
std::cout << "Signature is valid" << std::endl;
} else {
std::cout << "Bad signature" << std::endl;
}
}
// We can also do the verification in a single step if we
// have all the message
if (pubkey.canVerify() && pubkey.verifyMessage(arg, argSig, QCA::EMSA3_MD5)) {
std::cout << "Signature is valid" << std::endl;
} else {
std::cout << "Signature could not be verified" << std::endl;
}
}
return 0;
}

View File

@ -1,8 +1,10 @@
set(saslclient_bin_SRCS saslclient.cpp)
MY_AUTOMOC( saslclient_bin_SRCS)
add_executable(saslclient ${saslclient_bin_SRCS})
target_link_qca_libraries(saslclient)
target_link_libraries(saslclient ${QT_QTNETWORK_LIBRARY})
if(QT6)
target_link_libraries(saslclient Qt6::Network)
else()
target_link_libraries(saslclient Qt5::Network)
endif()

View File

@ -21,10 +21,10 @@
*/
#include <QCoreApplication>
#include <QTimer>
#include <QTcpSocket>
#include <QTcpServer>
#include <stdio.h>
#include <QTcpSocket>
#include <QTimer>
#include <cstdio>
// QtCrypto has the declarations for all of QCA
#include <QtCrypto>
@ -35,535 +35,527 @@
static QString prompt(const QString &s)
{
printf("* %s ", qPrintable(s));
fflush(stdout);
char line[256];
fgets(line, 255, stdin);
QString result = line;
if(result[result.length()-1] == '\n')
result.truncate(result.length()-1);
return result;
printf("* %s ", qPrintable(s));
fflush(stdout);
char line[256];
fgets(line, 255, stdin);
QString result = QString::fromLatin1(line);
if (result[result.length() - 1] == QLatin1Char('\n'))
result.truncate(result.length() - 1);
return result;
}
static QString socketErrorToString(QAbstractSocket::SocketError x)
{
QString s;
switch(x)
{
case QAbstractSocket::ConnectionRefusedError:
s = "connection refused or timed out"; break;
case QAbstractSocket::RemoteHostClosedError:
s = "remote host closed the connection"; break;
case QAbstractSocket::HostNotFoundError:
s = "host not found"; break;
case QAbstractSocket::SocketAccessError:
s = "access error"; break;
case QAbstractSocket::SocketResourceError:
s = "too many sockets"; break;
case QAbstractSocket::SocketTimeoutError:
s = "operation timed out"; break;
case QAbstractSocket::DatagramTooLargeError:
s = "datagram was larger than system limit"; break;
case QAbstractSocket::NetworkError:
s = "network error"; break;
case QAbstractSocket::AddressInUseError:
s = "address is already in use"; break;
case QAbstractSocket::SocketAddressNotAvailableError:
s = "address does not belong to the host"; break;
case QAbstractSocket::UnsupportedSocketOperationError:
s = "operation is not supported by the local operating system"; break;
default:
s = "unknown socket error"; break;
}
return s;
QString s;
switch (x) {
case QAbstractSocket::ConnectionRefusedError:
s = QStringLiteral("connection refused or timed out");
break;
case QAbstractSocket::RemoteHostClosedError:
s = QStringLiteral("remote host closed the connection");
break;
case QAbstractSocket::HostNotFoundError:
s = QStringLiteral("host not found");
break;
case QAbstractSocket::SocketAccessError:
s = QStringLiteral("access error");
break;
case QAbstractSocket::SocketResourceError:
s = QStringLiteral("too many sockets");
break;
case QAbstractSocket::SocketTimeoutError:
s = QStringLiteral("operation timed out");
break;
case QAbstractSocket::DatagramTooLargeError:
s = QStringLiteral("datagram was larger than system limit");
break;
case QAbstractSocket::NetworkError:
s = QStringLiteral("network error");
break;
case QAbstractSocket::AddressInUseError:
s = QStringLiteral("address is already in use");
break;
case QAbstractSocket::SocketAddressNotAvailableError:
s = QStringLiteral("address does not belong to the host");
break;
case QAbstractSocket::UnsupportedSocketOperationError:
s = QStringLiteral("operation is not supported by the local operating system");
break;
default:
s = QStringLiteral("unknown socket error");
break;
}
return s;
}
static QString saslAuthConditionToString(QCA::SASL::AuthCondition x)
{
QString s;
switch(x)
{
case QCA::SASL::NoMechanism:
s = "no appropriate mechanism could be negotiated"; break;
case QCA::SASL::BadProtocol:
s = "bad SASL protocol"; break;
case QCA::SASL::BadServer:
s = "server failed mutual authentication"; break;
// AuthFail or unknown (including those defined for server only)
default:
s = "generic authentication failure"; break;
};
return s;
QString s;
switch (x) {
case QCA::SASL::NoMechanism:
s = QStringLiteral("no appropriate mechanism could be negotiated");
break;
case QCA::SASL::BadProtocol:
s = QStringLiteral("bad SASL protocol");
break;
case QCA::SASL::BadServer:
s = QStringLiteral("server failed mutual authentication");
break;
// AuthFail or unknown (including those defined for server only)
default:
s = QStringLiteral("generic authentication failure");
break;
};
return s;
}
class ClientTest : public QObject
{
Q_OBJECT
Q_OBJECT
private:
QString host, proto, authzid, realm, user, pass;
int port;
bool no_authzid, no_realm;
int mode; // 0 = receive mechanism list, 1 = sasl negotiation, 2 = app
QTcpSocket *sock;
QCA::SASL *sasl;
QByteArray inbuf;
bool sock_done;
int waitCycles;
QString host, proto, authzid, realm, user, pass;
int port;
bool no_authzid, no_realm;
int mode; // 0 = receive mechanism list, 1 = sasl negotiation, 2 = app
QTcpSocket *sock;
QCA::SASL * sasl;
QByteArray inbuf;
bool sock_done;
int waitCycles;
public:
ClientTest(const QString &_host, int _port, const QString &_proto, const QString &_authzid, const QString &_realm, const QString &_user, const QString &_pass, bool _no_authzid, bool _no_realm) :
host(_host),
proto(_proto),
authzid(_authzid),
realm(_realm),
user(_user),
pass(_pass),
port(_port),
no_authzid(_no_authzid),
no_realm(_no_realm),
sock_done(false),
waitCycles(0)
{
sock = new QTcpSocket(this);
connect(sock, SIGNAL(connected()), SLOT(sock_connected()));
connect(sock, SIGNAL(readyRead()), SLOT(sock_readyRead()));
connect(sock, SIGNAL(error(QAbstractSocket::SocketError)), SLOT(sock_error(QAbstractSocket::SocketError)));
ClientTest(const QString &_host,
int _port,
const QString &_proto,
const QString &_authzid,
const QString &_realm,
const QString &_user,
const QString &_pass,
bool _no_authzid,
bool _no_realm)
: host(_host)
, proto(_proto)
, authzid(_authzid)
, realm(_realm)
, user(_user)
, pass(_pass)
, port(_port)
, no_authzid(_no_authzid)
, no_realm(_no_realm)
, sock_done(false)
, waitCycles(0)
{
sock = new QTcpSocket(this);
connect(sock, &QTcpSocket::connected, this, &ClientTest::sock_connected);
connect(sock, &QTcpSocket::readyRead, this, &ClientTest::sock_readyRead);
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
connect(sock, &QTcpSocket::errorOccurred, this, &ClientTest::sock_error);
#else
connect(sock, QOverload<QAbstractSocket::SocketError>::of(&QTcpSocket::error), this, &ClientTest::sock_error);
#endif
sasl = new QCA::SASL(this);
connect(sasl, SIGNAL(clientStarted(bool, const QByteArray &)), SLOT(sasl_clientFirstStep(bool, const QByteArray &)));
connect(sasl, SIGNAL(nextStep(const QByteArray &)), SLOT(sasl_nextStep(const QByteArray &)));
connect(sasl, SIGNAL(needParams(const QCA::SASL::Params &)), SLOT(sasl_needParams(const QCA::SASL::Params &)));
connect(sasl, SIGNAL(authenticated()), SLOT(sasl_authenticated()));
connect(sasl, SIGNAL(readyRead()), SLOT(sasl_readyRead()));
connect(sasl, SIGNAL(readyReadOutgoing()), SLOT(sasl_readyReadOutgoing()));
connect(sasl, SIGNAL(error()), SLOT(sasl_error()));
}
sasl = new QCA::SASL(this);
connect(sasl, &QCA::SASL::clientStarted, this, &ClientTest::sasl_clientFirstStep);
connect(sasl, &QCA::SASL::nextStep, this, &ClientTest::sasl_nextStep);
connect(sasl, &QCA::SASL::needParams, this, &ClientTest::sasl_needParams);
connect(sasl, &QCA::SASL::authenticated, this, &ClientTest::sasl_authenticated);
connect(sasl, &QCA::SASL::readyRead, this, &ClientTest::sasl_readyRead);
connect(sasl, &QCA::SASL::readyReadOutgoing, this, &ClientTest::sasl_readyReadOutgoing);
connect(sasl, &QCA::SASL::error, this, &ClientTest::sasl_error);
}
public slots:
void start()
{
mode = 0; // mech list mode
public Q_SLOTS:
void start()
{
mode = 0; // mech list mode
int flags = 0;
flags |= QCA::SASL::AllowPlain;
flags |= QCA::SASL::AllowAnonymous;
sasl->setConstraints((QCA::SASL::AuthFlags)flags, 0, 256);
int flags = 0;
flags |= QCA::SASL::AllowPlain;
flags |= QCA::SASL::AllowAnonymous;
sasl->setConstraints((QCA::SASL::AuthFlags)flags, 0, 256);
if(!user.isEmpty())
sasl->setUsername(user);
if(!authzid.isEmpty())
sasl->setAuthzid(authzid);
if(!pass.isEmpty())
sasl->setPassword(pass.toUtf8());
if(!realm.isEmpty())
sasl->setRealm(realm);
if (!user.isEmpty())
sasl->setUsername(user);
if (!authzid.isEmpty())
sasl->setAuthzid(authzid);
if (!pass.isEmpty())
sasl->setPassword(pass.toUtf8());
if (!realm.isEmpty())
sasl->setRealm(realm);
printf("Connecting to %s:%d, for protocol %s\n", qPrintable(host), port, qPrintable(proto));
sock->connectToHost(host, port);
}
printf("Connecting to %s:%d, for protocol %s\n", qPrintable(host), port, qPrintable(proto));
sock->connectToHost(host, port);
}
signals:
void quit();
Q_SIGNALS:
void quit();
private slots:
void sock_connected()
{
printf("Connected to server. Awaiting mechanism list...\n");
}
private Q_SLOTS:
void sock_connected()
{
printf("Connected to server. Awaiting mechanism list...\n");
}
void sock_error(QAbstractSocket::SocketError x)
{
if(x == QAbstractSocket::RemoteHostClosedError)
{
if(mode == 2) // app mode, where disconnect means completion
{
sock_done = true;
tryFinished();
return;
}
else // any other mode, where disconnect is an error
{
printf("Error: server closed connection unexpectedly.\n");
emit quit();
return;
}
}
void sock_error(QAbstractSocket::SocketError x)
{
if (x == QAbstractSocket::RemoteHostClosedError) {
if (mode == 2) // app mode, where disconnect means completion
{
sock_done = true;
tryFinished();
return;
} else // any other mode, where disconnect is an error
{
printf("Error: server closed connection unexpectedly.\n");
emit quit();
return;
}
}
printf("Error: socket: %s\n", qPrintable(socketErrorToString(x)));
emit quit();
}
printf("Error: socket: %s\n", qPrintable(socketErrorToString(x)));
emit quit();
}
void sock_readyRead()
{
if(mode == 2) // app mode
{
QByteArray a = sock->readAll();
printf("Read %d bytes\n", a.size());
void sock_readyRead()
{
if (mode == 2) // app mode
{
QByteArray a = sock->readAll();
printf("Read %d bytes\n", int(a.size()));
// there is a possible flaw in the qca 2.0 api, in
// that if sasl data is received from the peer
// followed by a disconnect from the peer, there is
// no clear approach to salvaging the bytes. tls is
// not affected because tls has the concept of
// closing a session. with sasl, there is no
// closing, and since the qca api is asynchronous,
// we could potentially wait forever for decoded
// data, if the last write was a partial packet.
//
// for now, we can perform a simple workaround of
// waiting at least three event loop cycles for
// decoded data before giving up and assuming the
// last write was partial. the fact is, all current
// qca sasl providers respond within this time
// frame, so this fix should work fine for now. in
// qca 2.1, we should revise the api to handle this
// situation better.
//
// further note: i guess this only affects application
// protocols that have no close message of their
// own, and rely on the tcp-level close. examples
// are http, and of course this qcatest protocol.
if(waitCycles == 0)
{
waitCycles = 3;
QMetaObject::invokeMethod(this, "waitWriteIncoming", Qt::QueuedConnection);
}
// there is a possible flaw in the qca 2.0 api, in
// that if sasl data is received from the peer
// followed by a disconnect from the peer, there is
// no clear approach to salvaging the bytes. tls is
// not affected because tls has the concept of
// closing a session. with sasl, there is no
// closing, and since the qca api is asynchronous,
// we could potentially wait forever for decoded
// data, if the last write was a partial packet.
//
// for now, we can perform a simple workaround of
// waiting at least three event loop cycles for
// decoded data before giving up and assuming the
// last write was partial. the fact is, all current
// qca sasl providers respond within this time
// frame, so this fix should work fine for now. in
// qca 2.1, we should revise the api to handle this
// situation better.
//
// further note: i guess this only affects application
// protocols that have no close message of their
// own, and rely on the tcp-level close. examples
// are http, and of course this qcatest protocol.
if (waitCycles == 0) {
waitCycles = 3;
QMetaObject::invokeMethod(this, "waitWriteIncoming", Qt::QueuedConnection);
}
sasl->writeIncoming(a);
}
else // mech list or sasl negotiation mode
{
if(sock->canReadLine())
{
QString line = sock->readLine();
line.truncate(line.length() - 1); // chop the newline
handleLine(line);
}
}
}
sasl->writeIncoming(a);
} else // mech list or sasl negotiation mode
{
if (sock->canReadLine()) {
QString line = QString::fromLatin1(sock->readLine());
line.truncate(line.length() - 1); // chop the newline
handleLine(line);
}
}
}
void sasl_clientFirstStep(bool clientInit, const QByteArray &clientInitData)
{
printf("Choosing mech: %s\n", qPrintable(sasl->mechanism()));
QString line = sasl->mechanism();
if(clientInit)
{
line += ' ';
line += arrayToString(clientInitData);
}
sendLine(line);
}
void sasl_clientFirstStep(bool clientInit, const QByteArray &clientInitData)
{
printf("Choosing mech: %s\n", qPrintable(sasl->mechanism()));
QString line = sasl->mechanism();
if (clientInit) {
line += QLatin1Char(' ');
line += arrayToString(clientInitData);
}
sendLine(line);
}
void sasl_nextStep(const QByteArray &stepData)
{
QString line = "C";
if(!stepData.isEmpty())
{
line += ',';
line += arrayToString(stepData);
}
sendLine(line);
}
void sasl_nextStep(const QByteArray &stepData)
{
QString line = QStringLiteral("C");
if (!stepData.isEmpty()) {
line += QLatin1Char(',');
line += arrayToString(stepData);
}
sendLine(line);
}
void sasl_needParams(const QCA::SASL::Params &params)
{
if(params.needUsername())
{
user = prompt("Username:");
sasl->setUsername(user);
}
void sasl_needParams(const QCA::SASL::Params &params)
{
if (params.needUsername()) {
user = prompt(QStringLiteral("Username:"));
sasl->setUsername(user);
}
if(params.canSendAuthzid() && !no_authzid)
{
authzid = prompt("Authorize As (enter to skip):");
if(!authzid.isEmpty())
sasl->setAuthzid(authzid);
}
if (params.canSendAuthzid() && !no_authzid) {
authzid = prompt(QStringLiteral("Authorize As (enter to skip):"));
if (!authzid.isEmpty())
sasl->setAuthzid(authzid);
}
if(params.needPassword())
{
QCA::ConsolePrompt prompt;
prompt.getHidden("* Password");
prompt.waitForFinished();
QCA::SecureArray pass = prompt.result();
sasl->setPassword(pass);
}
if (params.needPassword()) {
QCA::ConsolePrompt prompt;
prompt.getHidden(QStringLiteral("* Password"));
prompt.waitForFinished();
QCA::SecureArray pass = prompt.result();
sasl->setPassword(pass);
}
if(params.canSendRealm() && !no_realm)
{
QStringList realms = sasl->realmList();
printf("Available realms:\n");
if(realms.isEmpty())
printf(" (none specified)\n");
foreach(const QString &s, realms)
printf(" %s\n", qPrintable(s));
realm = prompt("Realm (enter to skip):");
if(!realm.isEmpty())
sasl->setRealm(realm);
}
if (params.canSendRealm() && !no_realm) {
QStringList realms = sasl->realmList();
printf("Available realms:\n");
if (realms.isEmpty())
printf(" (none specified)\n");
foreach (const QString &s, realms)
printf(" %s\n", qPrintable(s));
realm = prompt(QStringLiteral("Realm (enter to skip):"));
if (!realm.isEmpty())
sasl->setRealm(realm);
}
sasl->continueAfterParams();
}
sasl->continueAfterParams();
}
void sasl_authenticated()
{
printf("SASL success!\n");
printf("SSF: %d\n", sasl->ssf());
}
void sasl_authenticated()
{
printf("SASL success!\n");
printf("SSF: %d\n", sasl->ssf());
}
void sasl_readyRead()
{
QByteArray a = sasl->read();
inbuf += a;
processInbuf();
}
void sasl_readyRead()
{
QByteArray a = sasl->read();
inbuf += a;
processInbuf();
}
void sasl_readyReadOutgoing()
{
QByteArray a = sasl->readOutgoing();
sock->write(a);
}
void sasl_readyReadOutgoing()
{
QByteArray a = sasl->readOutgoing();
sock->write(a);
}
void sasl_error()
{
int e = sasl->errorCode();
if(e == QCA::SASL::ErrorInit)
printf("Error: sasl: initialization failed.\n");
else if(e == QCA::SASL::ErrorHandshake)
printf("Error: sasl: %s.\n", qPrintable(saslAuthConditionToString(sasl->authCondition())));
else if(e == QCA::SASL::ErrorCrypt)
printf("Error: sasl: broken security layer.\n");
else
printf("Error: sasl: unknown error.\n");
void sasl_error()
{
int e = sasl->errorCode();
if (e == QCA::SASL::ErrorInit)
printf("Error: sasl: initialization failed.\n");
else if (e == QCA::SASL::ErrorHandshake)
printf("Error: sasl: %s.\n", qPrintable(saslAuthConditionToString(sasl->authCondition())));
else if (e == QCA::SASL::ErrorCrypt)
printf("Error: sasl: broken security layer.\n");
else
printf("Error: sasl: unknown error.\n");
emit quit();
}
emit quit();
}
void waitWriteIncoming()
{
--waitCycles;
if(waitCycles > 0)
{
QMetaObject::invokeMethod(this, "waitWriteIncoming", Qt::QueuedConnection);
return;
}
void waitWriteIncoming()
{
--waitCycles;
if (waitCycles > 0) {
QMetaObject::invokeMethod(this, "waitWriteIncoming", Qt::QueuedConnection);
return;
}
tryFinished();
}
tryFinished();
}
private:
void tryFinished()
{
if(sock_done && waitCycles == 0)
{
printf("Finished, server closed connection.\n");
void tryFinished()
{
if (sock_done && waitCycles == 0) {
printf("Finished, server closed connection.\n");
// if we give up on waiting for a response to
// writeIncoming, then it might come late. in
// theory this shouldn't happen if we wait enough
// cycles, but if one were to arrive then it could
// occur between the request to quit the app and
// the actual quit of the app. to assist with
// debugging, then, we'll explicitly stop listening
// for signals here. otherwise the response may
// still be received and displayed, giving a false
// sense of correctness.
sasl->disconnect(this);
// if we give up on waiting for a response to
// writeIncoming, then it might come late. in
// theory this shouldn't happen if we wait enough
// cycles, but if one were to arrive then it could
// occur between the request to quit the app and
// the actual quit of the app. to assist with
// debugging, then, we'll explicitly stop listening
// for signals here. otherwise the response may
// still be received and displayed, giving a false
// sense of correctness.
sasl->disconnect(this);
emit quit();
}
}
emit quit();
}
}
QString arrayToString(const QByteArray &ba)
{
return QCA::Base64().arrayToString(ba);
}
QString arrayToString(const QByteArray &ba)
{
return QCA::Base64().arrayToString(ba);
}
QByteArray stringToArray(const QString &s)
{
return QCA::Base64().stringToArray(s).toByteArray();
}
QByteArray stringToArray(const QString &s)
{
return QCA::Base64().stringToArray(s).toByteArray();
}
void sendLine(const QString &line)
{
printf("Writing: {%s}\n", qPrintable(line));
QString s = line + '\n';
QByteArray a = s.toUtf8();
if(mode == 2) // app mode
sasl->write(a); // write to sasl
else // mech list or sasl negotiation
sock->write(a); // write to socket
}
void sendLine(const QString &line)
{
printf("Writing: {%s}\n", qPrintable(line));
QString s = line + QLatin1Char('\n');
QByteArray a = s.toUtf8();
if (mode == 2) // app mode
sasl->write(a); // write to sasl
else // mech list or sasl negotiation
sock->write(a); // write to socket
}
void processInbuf()
{
// collect completed lines from inbuf
QStringList list;
int at;
while((at = inbuf.indexOf('\n')) != -1)
{
list += QString::fromUtf8(inbuf.mid(0, at));
inbuf = inbuf.mid(at + 1);
}
void processInbuf()
{
// collect completed lines from inbuf
QStringList list;
int at;
while ((at = inbuf.indexOf('\n')) != -1) {
list += QString::fromUtf8(inbuf.mid(0, at));
inbuf = inbuf.mid(at + 1);
}
// process the lines
foreach(const QString &line, list)
handleLine(line);
}
// process the lines
foreach (const QString &line, list)
handleLine(line);
}
void handleLine(const QString &line)
{
printf("Reading: [%s]\n", qPrintable(line));
if(mode == 0)
{
// first line is the method list
QStringList mechlist = line.split(' ');
mode = 1; // switch to sasl negotiation mode
sasl->startClient(proto, host, mechlist);
}
else if(mode == 1)
{
QString type, rest;
int n = line.indexOf(',');
if(n != -1)
{
type = line.mid(0, n);
rest = line.mid(n + 1);
}
else
type = line;
if(type == "C")
{
sasl->putStep(stringToArray(rest));
}
else if(type == "E")
{
if(!rest.isEmpty())
printf("Error: server says: %s.\n", qPrintable(rest));
else
printf("Error: server error, unspecified.\n");
emit quit();
return;
}
else if(type == "A")
{
printf("Authentication success.\n");
mode = 2; // switch to app mode
void handleLine(const QString &line)
{
printf("Reading: [%s]\n", qPrintable(line));
if (mode == 0) {
// first line is the method list
const QStringList mechlist = line.split(QLatin1Char(' '));
mode = 1; // switch to sasl negotiation mode
sasl->startClient(proto, host, mechlist);
} else if (mode == 1) {
QString type, rest;
int n = line.indexOf(QLatin1Char(','));
if (n != -1) {
type = line.mid(0, n);
rest = line.mid(n + 1);
} else
type = line;
// at this point, the server may send us text
// lines for us to display and then close.
if (type == QLatin1String("C")) {
sasl->putStep(stringToArray(rest));
} else if (type == QLatin1String("E")) {
if (!rest.isEmpty())
printf("Error: server says: %s.\n", qPrintable(rest));
else
printf("Error: server error, unspecified.\n");
emit quit();
return;
} else if (type == QLatin1String("A")) {
printf("Authentication success.\n");
mode = 2; // switch to app mode
sock_readyRead(); // any extra data?
return;
}
else
{
printf("Error: Bad format from peer, closing.\n");
emit quit();
return;
}
}
}
// at this point, the server may send us text
// lines for us to display and then close.
sock_readyRead(); // any extra data?
return;
} else {
printf("Error: Bad format from peer, closing.\n");
emit quit();
return;
}
}
}
};
void usage()
{
printf("usage: saslclient (options) host(:port) (user) (pass)\n");
printf("options: --proto=x, --authzid=x, --realm=x\n");
printf("usage: saslclient (options) host(:port) (user) (pass)\n");
printf("options: --proto=x, --authzid=x, --realm=x\n");
}
int main(int argc, char **argv)
{
QCA::Initializer init;
QCoreApplication qapp(argc, argv);
QCA::Initializer init;
QCoreApplication qapp(argc, argv);
QStringList args = qapp.arguments();
args.removeFirst();
QStringList args = qapp.arguments();
args.removeFirst();
// options
QString proto = "qcatest"; // default protocol
QString authzid, realm;
bool no_authzid = false;
bool no_realm = false;
for(int n = 0; n < args.count(); ++n)
{
if(!args[n].startsWith("--"))
continue;
// options
QString proto = QStringLiteral("qcatest"); // default protocol
QString authzid, realm;
bool no_authzid = false;
bool no_realm = false;
for (int n = 0; n < args.count(); ++n) {
if (!args[n].startsWith(QLatin1String("--")))
continue;
QString opt = args[n].mid(2);
QString var, val;
int at = opt.indexOf('=');
if(at != -1)
{
var = opt.mid(0, at);
val = opt.mid(at + 1);
}
else
var = opt;
QString opt = args[n].mid(2);
QString var, val;
int at = opt.indexOf(QLatin1Char('='));
if (at != -1) {
var = opt.mid(0, at);
val = opt.mid(at + 1);
} else
var = opt;
if(var == "proto")
{
proto = val;
}
else if(var == "authzid")
{
// specifying empty authzid means force unspecified
if(val.isEmpty())
no_authzid = true;
else
authzid = val;
}
else if(var == "realm")
{
// specifying empty realm means force unspecified
if(val.isEmpty())
no_realm = true;
else
realm = val;
}
if (var == QLatin1String("proto")) {
proto = val;
} else if (var == QLatin1String("authzid")) {
// specifying empty authzid means force unspecified
if (val.isEmpty())
no_authzid = true;
else
authzid = val;
} else if (var == QLatin1String("realm")) {
// specifying empty realm means force unspecified
if (val.isEmpty())
no_realm = true;
else
realm = val;
}
args.removeAt(n);
--n; // adjust position
}
args.removeAt(n);
--n; // adjust position
}
if(args.count() < 1)
{
usage();
return 0;
}
if (args.count() < 1) {
usage();
return 0;
}
QString host, user, pass;
int port = 8001; // default port
QString host, user, pass;
int port = 8001; // default port
QString hostinput = args[0];
if(args.count() >= 2)
user = args[1];
if(args.count() >= 3)
pass = args[2];
QString hostinput = args[0];
if (args.count() >= 2)
user = args[1];
if (args.count() >= 3)
pass = args[2];
int at = hostinput.indexOf(':');
if(at != -1)
{
host = hostinput.mid(0, at);
port = hostinput.mid(at + 1).toInt();
}
else
host = hostinput;
int at = hostinput.indexOf(QLatin1Char(':'));
if (at != -1) {
host = hostinput.mid(0, at);
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 2)
port = QStringView(hostinput).mid(at + 1).toInt();
#else
port = hostinput.midRef(at + 1).toInt();
#endif
} else
host = hostinput;
if(!QCA::isSupported("sasl"))
{
printf("Error: SASL support not found.\n");
return 1;
}
if (!QCA::isSupported("sasl")) {
printf("Error: SASL support not found.\n");
return 1;
}
ClientTest client(host, port, proto, authzid, realm, user, pass, no_authzid, no_realm);
QObject::connect(&client, SIGNAL(quit()), &qapp, SLOT(quit()));
QTimer::singleShot(0, &client, SLOT(start()));
qapp.exec();
ClientTest client(host, port, proto, authzid, realm, user, pass, no_authzid, no_realm);
QObject::connect(&client, &ClientTest::quit, &qapp, &QCoreApplication::quit);
QTimer::singleShot(0, &client, &ClientTest::start);
qapp.exec();
return 0;
return 0;
}
#include "saslclient.moc"

View File

@ -1,8 +1,10 @@
set(saslserver_bin_SRCS saslserver.cpp)
MY_AUTOMOC( saslserver_bin_SRCS)
add_executable(saslserver ${saslserver_bin_SRCS})
target_link_qca_libraries(saslserver)
target_link_libraries(saslserver ${QT_QTNETWORK_LIBRARY})
if(QT6)
target_link_libraries(saslserver Qt6::Network)
else()
target_link_libraries(saslserver Qt5::Network)
endif()

View File

@ -21,10 +21,10 @@
*/
#include <QCoreApplication>
#include <QTimer>
#include <QTcpSocket>
#include <QTcpServer>
#include <stdio.h>
#include <QTcpSocket>
#include <QTimer>
#include <cstdio>
// QtCrypto has the declarations for all of QCA
#include <QtCrypto>
@ -35,480 +35,490 @@
static QString socketErrorToString(QAbstractSocket::SocketError x)
{
QString s;
switch(x)
{
case QAbstractSocket::ConnectionRefusedError:
s = "connection refused or timed out"; break;
case QAbstractSocket::RemoteHostClosedError:
s = "remote host closed the connection"; break;
case QAbstractSocket::HostNotFoundError:
s = "host not found"; break;
case QAbstractSocket::SocketAccessError:
s = "access error"; break;
case QAbstractSocket::SocketResourceError:
s = "too many sockets"; break;
case QAbstractSocket::SocketTimeoutError:
s = "operation timed out"; break;
case QAbstractSocket::DatagramTooLargeError:
s = "datagram was larger than system limit"; break;
case QAbstractSocket::NetworkError:
s = "network error"; break;
case QAbstractSocket::AddressInUseError:
s = "address is already in use"; break;
case QAbstractSocket::SocketAddressNotAvailableError:
s = "address does not belong to the host"; break;
case QAbstractSocket::UnsupportedSocketOperationError:
s = "operation is not supported by the local operating system"; break;
default:
s = "unknown socket error"; break;
}
return s;
QString s;
switch (x) {
case QAbstractSocket::ConnectionRefusedError:
s = QStringLiteral("connection refused or timed out");
break;
case QAbstractSocket::RemoteHostClosedError:
s = QStringLiteral("remote host closed the connection");
break;
case QAbstractSocket::HostNotFoundError:
s = QStringLiteral("host not found");
break;
case QAbstractSocket::SocketAccessError:
s = QStringLiteral("access error");
break;
case QAbstractSocket::SocketResourceError:
s = QStringLiteral("too many sockets");
break;
case QAbstractSocket::SocketTimeoutError:
s = QStringLiteral("operation timed out");
break;
case QAbstractSocket::DatagramTooLargeError:
s = QStringLiteral("datagram was larger than system limit");
break;
case QAbstractSocket::NetworkError:
s = QStringLiteral("network error");
break;
case QAbstractSocket::AddressInUseError:
s = QStringLiteral("address is already in use");
break;
case QAbstractSocket::SocketAddressNotAvailableError:
s = QStringLiteral("address does not belong to the host");
break;
case QAbstractSocket::UnsupportedSocketOperationError:
s = QStringLiteral("operation is not supported by the local operating system");
break;
default:
s = QStringLiteral("unknown socket error");
break;
}
return s;
}
static QString saslAuthConditionToString(QCA::SASL::AuthCondition x)
{
QString s;
switch(x)
{
case QCA::SASL::NoMechanism:
s = "no appropriate mechanism could be negotiated"; break;
case QCA::SASL::BadProtocol:
s = "bad SASL protocol"; break;
case QCA::SASL::BadAuth:
s = "authentication failed"; break;
case QCA::SASL::NoAuthzid:
s = "authorization failed"; break;
case QCA::SASL::TooWeak:
s = "mechanism too weak for this user"; break;
case QCA::SASL::NeedEncrypt:
s = "encryption is needed to use this mechanism"; break;
case QCA::SASL::Expired:
s = "passphrase expired"; break;
case QCA::SASL::Disabled:
s = "account is disabled"; break;
case QCA::SASL::NoUser:
s = "user not found"; break;
case QCA::SASL::RemoteUnavailable:
s = "needed remote service is unavailable"; break;
// AuthFail or unknown (including those defined for client only)
default:
s = "generic authentication failure"; break;
};
return s;
QString s;
switch (x) {
case QCA::SASL::NoMechanism:
s = QStringLiteral("no appropriate mechanism could be negotiated");
break;
case QCA::SASL::BadProtocol:
s = QStringLiteral("bad SASL protocol");
break;
case QCA::SASL::BadAuth:
s = QStringLiteral("authentication failed");
break;
case QCA::SASL::NoAuthzid:
s = QStringLiteral("authorization failed");
break;
case QCA::SASL::TooWeak:
s = QStringLiteral("mechanism too weak for this user");
break;
case QCA::SASL::NeedEncrypt:
s = QStringLiteral("encryption is needed to use this mechanism");
break;
case QCA::SASL::Expired:
s = QStringLiteral("passphrase expired");
break;
case QCA::SASL::Disabled:
s = QStringLiteral("account is disabled");
break;
case QCA::SASL::NoUser:
s = QStringLiteral("user not found");
break;
case QCA::SASL::RemoteUnavailable:
s = QStringLiteral("needed remote service is unavailable");
break;
// AuthFail or unknown (including those defined for client only)
default:
s = QStringLiteral("generic authentication failure");
break;
};
return s;
}
// --- ServerTest declaration
class ServerTest : public QObject
{
Q_OBJECT
Q_OBJECT
private:
QString host, proto, realm, str;
int port;
QTcpServer *tcpServer;
QList<int> ids;
QString host, proto, realm, str;
int port;
QTcpServer *tcpServer;
QList<int> ids;
public:
ServerTest(const QString &_host, int _port, const QString &_proto, const QString &_realm, const QString &_str);
ServerTest(const QString &_host, int _port, const QString &_proto, const QString &_realm, const QString &_str);
int reserveId();
void releaseId(int id);
int reserveId();
void releaseId(int id);
public slots:
void start();
public Q_SLOTS:
void start();
signals:
void quit();
Q_SIGNALS:
void quit();
private slots:
void server_newConnection();
private Q_SLOTS:
void server_newConnection();
};
// --- ServerTestHandler
class ServerTestHandler : public QObject
{
Q_OBJECT
Q_OBJECT
private:
ServerTest *serverTest;
QTcpSocket *sock;
QCA::SASL *sasl;
int id;
QString host, proto, realm, str;
int mode; // 0 = receive mechanism list, 1 = sasl negotiation, 2 = app
int toWrite;
ServerTest *serverTest;
QTcpSocket *sock;
QCA::SASL * sasl;
int id;
QString host, proto, realm, str;
int mode; // 0 = receive mechanism list, 1 = sasl negotiation, 2 = app
int toWrite;
public:
ServerTestHandler(ServerTest *_serverTest, QTcpSocket *_sock, const QString &_host, const QString &_proto, const QString &_realm, const QString &_str) :
serverTest(_serverTest),
sock(_sock),
host(_host),
proto(_proto),
realm(_realm),
str(_str)
{
id = serverTest->reserveId();
ServerTestHandler(ServerTest * _serverTest,
QTcpSocket * _sock,
const QString &_host,
const QString &_proto,
const QString &_realm,
const QString &_str)
: serverTest(_serverTest)
, sock(_sock)
, host(_host)
, proto(_proto)
, realm(_realm)
, str(_str)
{
id = serverTest->reserveId();
sock->setParent(this);
connect(sock, SIGNAL(disconnected()), SLOT(sock_disconnected()));
connect(sock, SIGNAL(readyRead()), SLOT(sock_readyRead()));
connect(sock, SIGNAL(error(QAbstractSocket::SocketError)), SLOT(sock_error(QAbstractSocket::SocketError)));
connect(sock, SIGNAL(bytesWritten(qint64)), SLOT(sock_bytesWritten(qint64)));
sock->setParent(this);
connect(sock, &QTcpSocket::disconnected, this, &ServerTestHandler::sock_disconnected);
connect(sock, &QTcpSocket::readyRead, this, &ServerTestHandler::sock_readyRead);
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
connect(sock, &QTcpSocket::errorOccurred, this, &ServerTestHandler::sock_error);
#else
connect(sock,
QOverload<QAbstractSocket::SocketError>::of(&QTcpSocket::error),
this,
&ServerTestHandler::sock_error);
#endif
connect(sock, &QTcpSocket::bytesWritten, this, &ServerTestHandler::sock_bytesWritten);
sasl = new QCA::SASL(this);
connect(sasl, SIGNAL(authCheck(const QString &, const QString &)), SLOT(sasl_authCheck(const QString &, const QString &)));
connect(sasl, SIGNAL(nextStep(const QByteArray &)), SLOT(sasl_nextStep(const QByteArray &)));
connect(sasl, SIGNAL(authenticated()), SLOT(sasl_authenticated()));
connect(sasl, SIGNAL(readyRead()), SLOT(sasl_readyRead()));
connect(sasl, SIGNAL(readyReadOutgoing()), SLOT(sasl_readyReadOutgoing()));
connect(sasl, SIGNAL(error()), SLOT(sasl_error()));
connect(sasl, SIGNAL(serverStarted()), SLOT(sasl_serverStarted()));
sasl = new QCA::SASL(this);
connect(sasl, &QCA::SASL::authCheck, this, &ServerTestHandler::sasl_authCheck);
connect(sasl, &QCA::SASL::nextStep, this, &ServerTestHandler::sasl_nextStep);
connect(sasl, &QCA::SASL::authenticated, this, &ServerTestHandler::sasl_authenticated);
connect(sasl, &QCA::SASL::readyRead, this, &ServerTestHandler::sasl_readyRead);
connect(sasl, &QCA::SASL::readyReadOutgoing, this, &ServerTestHandler::sasl_readyReadOutgoing);
connect(sasl, &QCA::SASL::error, this, &ServerTestHandler::sasl_error);
connect(sasl, &QCA::SASL::serverStarted, this, &ServerTestHandler::sasl_serverStarted);
mode = 0; // mech list mode
toWrite = 0;
mode = 0; // mech list mode
toWrite = 0;
int flags = 0;
flags |= QCA::SASL::AllowPlain;
flags |= QCA::SASL::AllowAnonymous;
sasl->setConstraints((QCA::SASL::AuthFlags)flags, 0, 256);
int flags = 0;
flags |= QCA::SASL::AllowPlain;
flags |= QCA::SASL::AllowAnonymous;
sasl->setConstraints((QCA::SASL::AuthFlags)flags, 0, 256);
printf("%d: Connection received! Starting SASL handshake...\n", id);
sasl->startServer(proto, host, realm);
}
printf("%d: Connection received! Starting SASL handshake...\n", id);
sasl->startServer(proto, host, realm);
}
~ServerTestHandler()
{
serverTest->releaseId(id);
}
~ServerTestHandler() override
{
serverTest->releaseId(id);
}
private slots:
void sasl_serverStarted()
{
sendLine(sasl->mechanismList().join(" "));
}
private Q_SLOTS:
void sasl_serverStarted()
{
sendLine(sasl->mechanismList().join(QStringLiteral(" ")));
}
void sock_disconnected()
{
printf("%d: Connection closed.\n", id);
discard();
}
void sock_disconnected()
{
printf("%d: Connection closed.\n", id);
discard();
}
void sock_error(QAbstractSocket::SocketError x)
{
if(x == QAbstractSocket::RemoteHostClosedError)
{
printf("%d: Error: client closed connection unexpectedly.\n", id);
discard();
return;
}
void sock_error(QAbstractSocket::SocketError x)
{
if (x == QAbstractSocket::RemoteHostClosedError) {
printf("%d: Error: client closed connection unexpectedly.\n", id);
discard();
return;
}
printf("%d: Error: socket: %s\n", id, qPrintable(socketErrorToString(x)));
discard();
}
printf("%d: Error: socket: %s\n", id, qPrintable(socketErrorToString(x)));
discard();
}
void sock_readyRead()
{
if(sock->canReadLine())
{
QString line = sock->readLine();
line.truncate(line.length() - 1); // chop the newline
handleLine(line);
}
}
void sock_readyRead()
{
if (sock->canReadLine()) {
QString line = QString::fromLatin1(sock->readLine());
line.truncate(line.length() - 1); // chop the newline
handleLine(line);
}
}
void sock_bytesWritten(qint64 x)
{
if(mode == 2) // app mode
{
toWrite -= sasl->convertBytesWritten(x);
if(toWrite == 0)
{
printf("%d: Sent, closing.\n", id);
sock->close();
}
}
}
void sock_bytesWritten(qint64 x)
{
if (mode == 2) // app mode
{
toWrite -= sasl->convertBytesWritten(x);
if (toWrite == 0) {
printf("%d: Sent, closing.\n", id);
sock->close();
}
}
}
void sasl_nextStep(const QByteArray &stepData)
{
QString line = "C";
if(!stepData.isEmpty())
{
line += ',';
line += arrayToString(stepData);
}
sendLine(line);
}
void sasl_nextStep(const QByteArray &stepData)
{
QString line = QStringLiteral("C");
if (!stepData.isEmpty()) {
line += QLatin1Char(',');
line += arrayToString(stepData);
}
sendLine(line);
}
void sasl_authCheck(const QString &user, const QString &authzid)
{
printf("%d: AuthCheck: User: [%s], Authzid: [%s]\n", id, qPrintable(user), qPrintable(authzid));
void sasl_authCheck(const QString &user, const QString &authzid)
{
printf("%d: AuthCheck: User: [%s], Authzid: [%s]\n", id, qPrintable(user), qPrintable(authzid));
// user - who has logged in, confirmed by sasl
// authzid - the identity the user wishes to act as, which
// could be another user or just any arbitrary string (in
// XMPP, this field holds a Jabber ID, for example). this
// field is not necessarily confirmed by sasl, and the
// decision about whether the user can act as the authzid
// must be made by the app.
// user - who has logged in, confirmed by sasl
// authzid - the identity the user wishes to act as, which
// could be another user or just any arbitrary string (in
// XMPP, this field holds a Jabber ID, for example). this
// field is not necessarily confirmed by sasl, and the
// decision about whether the user can act as the authzid
// must be made by the app.
// for this simple example program, we allow anyone to use
// the service, and simply continue onward with the
// negotiation.
sasl->continueAfterAuthCheck();
}
// for this simple example program, we allow anyone to use
// the service, and simply continue onward with the
// negotiation.
sasl->continueAfterAuthCheck();
}
void sasl_authenticated()
{
sendLine("A");
printf("%d: Authentication success.\n", id);
mode = 2; // switch to app mode
printf("%d: SSF: %d\n", id, sasl->ssf());
sendLine(str);
}
void sasl_authenticated()
{
sendLine(QStringLiteral("A"));
printf("%d: Authentication success.\n", id);
mode = 2; // switch to app mode
printf("%d: SSF: %d\n", id, sasl->ssf());
sendLine(str);
}
void sasl_readyRead()
{
QByteArray a = sasl->read();
printf("%d: Warning, client sent %d bytes unexpectedly.\n", id, a.size());
}
void sasl_readyRead()
{
QByteArray a = sasl->read();
printf("%d: Warning, client sent %d bytes unexpectedly.\n", id, int(a.size()));
}
void sasl_readyReadOutgoing()
{
sock->write(sasl->readOutgoing());
}
void sasl_readyReadOutgoing()
{
sock->write(sasl->readOutgoing());
}
void sasl_error()
{
int e = sasl->errorCode();
if(e == QCA::SASL::ErrorInit)
{
printf("%d: Error: sasl: initialization failed.\n", id);
}
else if(e == QCA::SASL::ErrorHandshake)
{
QString errstr = saslAuthConditionToString(sasl->authCondition());
sendLine(QString("E,") + errstr);
printf("%d: Error: sasl: %s.\n", id, qPrintable(errstr));
}
else if(e == QCA::SASL::ErrorCrypt)
{
printf("%d: Error: sasl: broken security layer.\n", id);
}
else
{
printf("%d: Error: sasl: unknown error.\n", id);
}
void sasl_error()
{
int e = sasl->errorCode();
if (e == QCA::SASL::ErrorInit) {
printf("%d: Error: sasl: initialization failed.\n", id);
} else if (e == QCA::SASL::ErrorHandshake) {
QString errstr = saslAuthConditionToString(sasl->authCondition());
sendLine(QStringLiteral("E,") + errstr);
printf("%d: Error: sasl: %s.\n", id, qPrintable(errstr));
} else if (e == QCA::SASL::ErrorCrypt) {
printf("%d: Error: sasl: broken security layer.\n", id);
} else {
printf("%d: Error: sasl: unknown error.\n", id);
}
sock->close();
}
sock->close();
}
private:
void discard()
{
deleteLater();
}
void discard()
{
deleteLater();
}
void handleLine(const QString &line)
{
printf("%d: Reading: [%s]\n", id, qPrintable(line));
if(mode == 0)
{
int n = line.indexOf(' ');
if(n != -1)
{
QString mech = line.mid(0, n);
QString rest = line.mid(n + 1).toUtf8();
sasl->putServerFirstStep(mech, stringToArray(rest));
}
else
sasl->putServerFirstStep(line);
++mode;
}
else if(mode == 1)
{
QString type, rest;
int n = line.indexOf(',');
if(n != -1)
{
type = line.mid(0, n);
rest = line.mid(n + 1);
}
else
{
type = line;
rest = "";
}
void handleLine(const QString &line)
{
printf("%d: Reading: [%s]\n", id, qPrintable(line));
if (mode == 0) {
int n = line.indexOf(QLatin1Char(' '));
if (n != -1) {
QString mech = line.mid(0, n);
QString rest = QString::fromLatin1(line.mid(n + 1).toUtf8());
sasl->putServerFirstStep(mech, stringToArray(rest));
} else
sasl->putServerFirstStep(line);
++mode;
} else if (mode == 1) {
QString type, rest;
int n = line.indexOf(QLatin1Char(','));
if (n != -1) {
type = line.mid(0, n);
rest = line.mid(n + 1);
} else {
type = line;
rest = QLatin1String("");
}
if(type == "C")
{
sasl->putStep(stringToArray(rest));
}
else
{
printf("%d: Bad format from peer, closing.\n", id);
sock->close();
return;
}
}
}
if (type == QLatin1String("C")) {
sasl->putStep(stringToArray(rest));
} else {
printf("%d: Bad format from peer, closing.\n", id);
sock->close();
return;
}
}
}
QString arrayToString(const QByteArray &ba)
{
QCA::Base64 encoder;
return encoder.arrayToString(ba);
}
QString arrayToString(const QByteArray &ba)
{
QCA::Base64 encoder;
return encoder.arrayToString(ba);
}
QByteArray stringToArray(const QString &s)
{
QCA::Base64 decoder(QCA::Decode);
return decoder.stringToArray(s).toByteArray();
}
QByteArray stringToArray(const QString &s)
{
QCA::Base64 decoder(QCA::Decode);
return decoder.stringToArray(s).toByteArray();
}
void sendLine(const QString &line)
{
printf("%d: Writing: {%s}\n", id, qPrintable(line));
QString s = line + '\n';
QByteArray a = s.toUtf8();
if(mode == 2) // app mode
{
toWrite += a.size();
sasl->write(a); // write to sasl
}
else // mech list or sasl negotiation
sock->write(a); // write to socket
}
void sendLine(const QString &line)
{
printf("%d: Writing: {%s}\n", id, qPrintable(line));
QString s = line + QLatin1Char('\n');
QByteArray a = s.toUtf8();
if (mode == 2) // app mode
{
toWrite += a.size();
sasl->write(a); // write to sasl
} else // mech list or sasl negotiation
sock->write(a); // write to socket
}
};
// --- ServerTest implementation
ServerTest::ServerTest(const QString &_host, int _port, const QString &_proto, const QString &_realm, const QString &_str) :
host(_host),
proto(_proto),
realm(_realm),
str(_str),
port(_port)
ServerTest::ServerTest(const QString &_host,
int _port,
const QString &_proto,
const QString &_realm,
const QString &_str)
: host(_host)
, proto(_proto)
, realm(_realm)
, str(_str)
, port(_port)
{
tcpServer = new QTcpServer(this);
connect(tcpServer, SIGNAL(newConnection()), SLOT(server_newConnection()));
tcpServer = new QTcpServer(this);
connect(tcpServer, &QTcpServer::newConnection, this, &ServerTest::server_newConnection);
}
int ServerTest::reserveId()
{
int n = 0;
while(ids.contains(n))
++n;
ids += n;
return n;
int n = 0;
while (ids.contains(n))
++n;
ids += n;
return n;
}
void ServerTest::releaseId(int id)
{
ids.removeAll(id);
ids.removeAll(id);
}
void ServerTest::start()
{
if(!tcpServer->listen(QHostAddress::Any, port))
{
printf("Error: unable to bind to port %d.\n", port);
emit quit();
return;
}
if (!tcpServer->listen(QHostAddress::Any, port)) {
printf("Error: unable to bind to port %d.\n", port);
emit quit();
return;
}
printf("Serving on %s:%d, for protocol %s ...\n", qPrintable(host), port, qPrintable(proto));
printf("Serving on %s:%d, for protocol %s ...\n", qPrintable(host), port, qPrintable(proto));
}
void ServerTest::server_newConnection()
{
QTcpSocket *sock = tcpServer->nextPendingConnection();
new ServerTestHandler(this, sock, host, proto, realm, str);
QTcpSocket *sock = tcpServer->nextPendingConnection();
new ServerTestHandler(this, sock, host, proto, realm, str);
}
// ---
void usage()
{
printf("usage: saslserver host (message)\n");
printf("options: --proto=x, --realm=x\n");
printf("usage: saslserver host (message)\n");
printf("options: --proto=x, --realm=x\n");
}
int main(int argc, char **argv)
{
QCA::Initializer init;
QCoreApplication qapp(argc, argv);
QCA::Initializer init;
QCoreApplication qapp(argc, argv);
QCA::setAppName("saslserver");
QCA::setAppName(QStringLiteral("saslserver"));
QStringList args = qapp.arguments();
args.removeFirst();
QStringList args = qapp.arguments();
args.removeFirst();
// options
QString proto = "qcatest"; // default protocol
QString realm;
for(int n = 0; n < args.count(); ++n)
{
if(!args[n].startsWith("--"))
continue;
// options
QString proto = QStringLiteral("qcatest"); // default protocol
QString realm;
for (int n = 0; n < args.count(); ++n) {
if (!args[n].startsWith(QLatin1String("--")))
continue;
QString opt = args[n].mid(2);
QString var, val;
int at = opt.indexOf('=');
if(at != -1)
{
var = opt.mid(0, at);
val = opt.mid(at + 1);
}
else
var = opt;
QString opt = args[n].mid(2);
QString var, val;
int at = opt.indexOf(QLatin1Char('='));
if (at != -1) {
var = opt.mid(0, at);
val = opt.mid(at + 1);
} else
var = opt;
if(var == "proto")
proto = val;
else if(var == "realm")
realm = val;
if (var == QLatin1String("proto"))
proto = val;
else if (var == QLatin1String("realm"))
realm = val;
args.removeAt(n);
--n; // adjust position
}
args.removeAt(n);
--n; // adjust position
}
if(args.count() < 1)
{
usage();
return 0;
}
if (args.count() < 1) {
usage();
return 0;
}
QString host;
int port = 8001; // default port
QString host;
int port = 8001; // default port
QString hostinput = args[0];
QString str = "Hello, World";
if(args.count() >= 2)
str = args[1];
QString hostinput = args[0];
QString str = QStringLiteral("Hello, World");
if (args.count() >= 2)
str = args[1];
int at = hostinput.indexOf(':');
if(at != -1)
{
host = hostinput.mid(0, at);
port = hostinput.mid(at + 1).toInt();
}
else
host = hostinput;
int at = hostinput.indexOf(QLatin1Char(':'));
if (at != -1) {
host = hostinput.mid(0, at);
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 2)
port = QStringView(hostinput).mid(at + 1).toInt();
#else
port = hostinput.midRef(at + 1).toInt();
#endif
} else
host = hostinput;
if(!QCA::isSupported("sasl"))
{
printf("Error: SASL support not found.\n");
return 1;
}
if (!QCA::isSupported("sasl")) {
printf("Error: SASL support not found.\n");
return 1;
}
ServerTest server(host, port, proto, realm, str);
QObject::connect(&server, SIGNAL(quit()), &qapp, SLOT(quit()));
QTimer::singleShot(0, &server, SLOT(start()));
qapp.exec();
ServerTest server(host, port, proto, realm, str);
QObject::connect(&server, &ServerTest::quit, &qapp, &QCoreApplication::quit);
QTimer::singleShot(0, &server, &ServerTest::start);
qapp.exec();
return 0;
return 0;
}
#include "saslserver.moc"

View File

@ -1,8 +1,10 @@
set(sslservtest_bin_SRCS sslservtest.cpp)
MY_AUTOMOC( sslservtest_bin_SRCS )
add_executable(sslservtest ${sslservtest_bin_SRCS})
target_link_qca_libraries(sslservtest)
target_link_libraries(sslservtest ${QT_QTNETWORK_LIBRARY})
if(QT6)
target_link_libraries(sslservtest Qt6::Network)
else()
target_link_libraries(sslservtest Qt5::Network)
endif()

View File

@ -34,218 +34,227 @@
#endif
char pemdata_cert[] =
"-----BEGIN CERTIFICATE-----\n"
"MIICeTCCAeKgAwIBAgIRAKKKnOj6Aarmwf0phApitVAwDQYJKoZIhvcNAQEFBQAw\n"
"ODELMAkGA1UEBhMCVVMxFDASBgNVBAoTC0V4YW1wbGUgT3JnMRMwEQYDVQQDEwpF\n"
"eGFtcGxlIENBMB4XDTA2MDMxNTA3MDU1MloXDTA3MDMxNTA3MDU1MlowOjEVMBMG\n"
"A1UEAxMMRXhhbXBsZSBVc2VyMQswCQYDVQQGEwJVUzEUMBIGA1UEChMLRXhhbXBs\n"
"ZSBPcmcwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAPkKn0FfHMvRZv+3uFcw\n"
"VrOadJmANzLVeVW/DHZp4CXokXSksM66ZMqFuQRBk5rnIZZpZmVp1tTRDVt9sEAY\n"
"YNa8CRM4HXkVlU0lCKdey18CSq2VuSvNtw8dDpoBmQt3nr9tePvKHnpS3nm6YjR2\n"
"NEvIKt1P4mHzYXLmwoF24C1bAgMBAAGjgYAwfjAdBgNVHQ4EFgQUmQIdzyDaPYWF\n"
"fPJ8PPOOm1eSsucwHwYDVR0jBBgwFoAUkCglAizTO7iqwLeaO6r/8kJuqhMwDAYD\n"
"VR0TAQH/BAIwADAeBgNVHREEFzAVgRNleGFtcGxlQGV4YW1wbGUuY29tMA4GA1Ud\n"
"DwEB/wQEAwIF4DANBgkqhkiG9w0BAQUFAAOBgQAuhbiUgy2a++EUccaonID7eTJZ\n"
"F3D5qXMqUpQxlYxU8du+9AxDD7nFxTMkQC2pzfmEc1znRNmJ1ZeLRL72VYsVndcT\n"
"psyM8ABkvPp1d2jWIyccVjGpt+/RN5IPKm/YIbtIZcywvWuXrOp1lanVmppLfPnO\n"
"6yneBkC9iqjOv/+Q+A==\n"
"-----END CERTIFICATE-----\n";
"-----BEGIN CERTIFICATE-----\n"
"MIICeTCCAeKgAwIBAgIRAKKKnOj6Aarmwf0phApitVAwDQYJKoZIhvcNAQEFBQAw\n"
"ODELMAkGA1UEBhMCVVMxFDASBgNVBAoTC0V4YW1wbGUgT3JnMRMwEQYDVQQDEwpF\n"
"eGFtcGxlIENBMB4XDTA2MDMxNTA3MDU1MloXDTA3MDMxNTA3MDU1MlowOjEVMBMG\n"
"A1UEAxMMRXhhbXBsZSBVc2VyMQswCQYDVQQGEwJVUzEUMBIGA1UEChMLRXhhbXBs\n"
"ZSBPcmcwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAPkKn0FfHMvRZv+3uFcw\n"
"VrOadJmANzLVeVW/DHZp4CXokXSksM66ZMqFuQRBk5rnIZZpZmVp1tTRDVt9sEAY\n"
"YNa8CRM4HXkVlU0lCKdey18CSq2VuSvNtw8dDpoBmQt3nr9tePvKHnpS3nm6YjR2\n"
"NEvIKt1P4mHzYXLmwoF24C1bAgMBAAGjgYAwfjAdBgNVHQ4EFgQUmQIdzyDaPYWF\n"
"fPJ8PPOOm1eSsucwHwYDVR0jBBgwFoAUkCglAizTO7iqwLeaO6r/8kJuqhMwDAYD\n"
"VR0TAQH/BAIwADAeBgNVHREEFzAVgRNleGFtcGxlQGV4YW1wbGUuY29tMA4GA1Ud\n"
"DwEB/wQEAwIF4DANBgkqhkiG9w0BAQUFAAOBgQAuhbiUgy2a++EUccaonID7eTJZ\n"
"F3D5qXMqUpQxlYxU8du+9AxDD7nFxTMkQC2pzfmEc1znRNmJ1ZeLRL72VYsVndcT\n"
"psyM8ABkvPp1d2jWIyccVjGpt+/RN5IPKm/YIbtIZcywvWuXrOp1lanVmppLfPnO\n"
"6yneBkC9iqjOv/+Q+A==\n"
"-----END CERTIFICATE-----\n";
char pemdata_privkey[] =
"-----BEGIN PRIVATE KEY-----\n"
"MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAPkKn0FfHMvRZv+3\n"
"uFcwVrOadJmANzLVeVW/DHZp4CXokXSksM66ZMqFuQRBk5rnIZZpZmVp1tTRDVt9\n"
"sEAYYNa8CRM4HXkVlU0lCKdey18CSq2VuSvNtw8dDpoBmQt3nr9tePvKHnpS3nm6\n"
"YjR2NEvIKt1P4mHzYXLmwoF24C1bAgMBAAECgYEAyIjJHDaeVXDU42zovyxpZE4n\n"
"PcOEryY+gdFJE8DFgUD4f1huFsj4iCuNg+PaG42p+hf9IARNvSho/RcEaVg4AJrV\n"
"jRP8r7fSqcIGr6lGuvDFFv3SU5ddy84g5oqLYGKvuPSHMGfVsZSxAwOrzD4bH19L\n"
"SNqtNcpdBsBd7ZiEE4ECQQD/oJGui9D5Dx3QVcS+QV4F8wuyN9jYIANmX/17o0fl\n"
"BL0bwRU4RICwadrcybi5N0JQLIYSUm2HGqNvAJbtnuQxAkEA+WeYLLYPeawcy+WU\n"
"kGcOR7BUjHiG71+6cvU4XIDW2bezA04fqWXkZRFAwHTMpQb785/XalFftgS21kql\n"
"8yLDSwJAHkeT2hwftdDPlEUEmBDAJW5DvWmWGwu3u2G1cfbGZl9oUyhM7ixXHg57\n"
"6VlPs0jTZxHPE86FwNIr99MXDbCbkQJBAMDFOJK+ecGirXNP1P+0GA6DFSap9inJ\n"
"BRTbwx+EmgwX966DUOefEOSpbDIVVSPs/Qr2LgtIMEFA7Y0+j3wZD3cCQBsTwccd\n"
"ASQx59xakpq11eOlTYz14rjwodr4QMyj26WxEPJtz7hKokx/+EH6fWuPIUSrROM5\n"
"07y2gaVbYxtis0s=\n"
"-----END PRIVATE KEY-----\n";
"-----BEGIN PRIVATE KEY-----\n"
"MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAPkKn0FfHMvRZv+3\n"
"uFcwVrOadJmANzLVeVW/DHZp4CXokXSksM66ZMqFuQRBk5rnIZZpZmVp1tTRDVt9\n"
"sEAYYNa8CRM4HXkVlU0lCKdey18CSq2VuSvNtw8dDpoBmQt3nr9tePvKHnpS3nm6\n"
"YjR2NEvIKt1P4mHzYXLmwoF24C1bAgMBAAECgYEAyIjJHDaeVXDU42zovyxpZE4n\n"
"PcOEryY+gdFJE8DFgUD4f1huFsj4iCuNg+PaG42p+hf9IARNvSho/RcEaVg4AJrV\n"
"jRP8r7fSqcIGr6lGuvDFFv3SU5ddy84g5oqLYGKvuPSHMGfVsZSxAwOrzD4bH19L\n"
"SNqtNcpdBsBd7ZiEE4ECQQD/oJGui9D5Dx3QVcS+QV4F8wuyN9jYIANmX/17o0fl\n"
"BL0bwRU4RICwadrcybi5N0JQLIYSUm2HGqNvAJbtnuQxAkEA+WeYLLYPeawcy+WU\n"
"kGcOR7BUjHiG71+6cvU4XIDW2bezA04fqWXkZRFAwHTMpQb785/XalFftgS21kql\n"
"8yLDSwJAHkeT2hwftdDPlEUEmBDAJW5DvWmWGwu3u2G1cfbGZl9oUyhM7ixXHg57\n"
"6VlPs0jTZxHPE86FwNIr99MXDbCbkQJBAMDFOJK+ecGirXNP1P+0GA6DFSap9inJ\n"
"BRTbwx+EmgwX966DUOefEOSpbDIVVSPs/Qr2LgtIMEFA7Y0+j3wZD3cCQBsTwccd\n"
"ASQx59xakpq11eOlTYz14rjwodr4QMyj26WxEPJtz7hKokx/+EH6fWuPIUSrROM5\n"
"07y2gaVbYxtis0s=\n"
"-----END PRIVATE KEY-----\n";
class SecureServer : public QObject
{
Q_OBJECT
public:
enum { Idle, Handshaking, Active, Closing };
SecureServer(quint16 _port) : port(_port)
enum
{
server = new QTcpServer;
connect( server, SIGNAL(newConnection()), SLOT(server_handleConnection()) );
Idle,
Handshaking,
Active,
Closing
};
ssl = new QCA::TLS;
connect(ssl, SIGNAL(handshaken()), SLOT(ssl_handshaken()));
connect(ssl, SIGNAL(readyRead()), SLOT(ssl_readyRead()));
connect(ssl, SIGNAL(readyReadOutgoing()), SLOT(ssl_readyReadOutgoing()));
connect(ssl, SIGNAL(closed()), SLOT(ssl_closed()));
connect(ssl, SIGNAL(error()), SLOT(ssl_error()));
SecureServer(quint16 _port)
: port(_port)
{
server = new QTcpServer;
connect(server, &QTcpServer::newConnection, this, &SecureServer::server_handleConnection);
cert = QCA::Certificate::fromPEM(pemdata_cert);
privkey = QCA::PrivateKey::fromPEM(pemdata_privkey);
ssl = new QCA::TLS;
connect(ssl, &QCA::TLS::handshaken, this, &SecureServer::ssl_handshaken);
connect(ssl, &QCA::TLS::readyRead, this, &SecureServer::ssl_readyRead);
connect(ssl, &QCA::TLS::readyReadOutgoing, this, &SecureServer::ssl_readyReadOutgoing);
connect(ssl, &QCA::TLS::closed, this, &SecureServer::ssl_closed);
connect(ssl, &QCA::TLS::error, this, &SecureServer::ssl_error);
mode = Idle;
cert = QCA::Certificate::fromPEM(QString::fromLatin1(pemdata_cert));
privkey = QCA::PrivateKey::fromPEM(QString::fromLatin1(pemdata_privkey));
mode = Idle;
}
~SecureServer()
~SecureServer() override
{
delete ssl;
delete server;
delete ssl;
delete server;
}
void start()
{
if(cert.isNull()) {
qDebug() << "Error loading cert!";
QTimer::singleShot(0, this, SIGNAL(quit()));
return;
}
if(privkey.isNull()) {
qDebug() << "Error loading private key!";
QTimer::singleShot(0, this, SIGNAL(quit()));
return;
}
if(false == server->listen(QHostAddress::Any, port)) {
qDebug() << "Error binding to port " << port;
QTimer::singleShot(0, this, SIGNAL(quit()));
return;
}
qDebug() << "Listening on port" << port;
if (cert.isNull()) {
qDebug() << "Error loading cert!";
QTimer::singleShot(0, this, &SecureServer::quit);
return;
}
if (privkey.isNull()) {
qDebug() << "Error loading private key!";
QTimer::singleShot(0, this, &SecureServer::quit);
return;
}
if (false == server->listen(QHostAddress::Any, port)) {
qDebug() << "Error binding to port " << port;
QTimer::singleShot(0, this, &SecureServer::quit);
return;
}
qDebug() << "Listening on port" << port;
}
signals:
Q_SIGNALS:
void quit();
private slots:
private Q_SLOTS:
void sock_readyRead()
{
QByteArray buf(sock->bytesAvailable(), 0x00);
QByteArray buf(sock->bytesAvailable(), 0x00);
int num = sock->read(buf.data(), buf.size());
int num = sock->read(buf.data(), buf.size());
if ( -1 == num )
qDebug() << "Error reading data from socket";
if (-1 == num)
qDebug() << "Error reading data from socket";
if (num < buf.size() )
buf.resize(num);
if (num < buf.size())
buf.resize(num);
ssl->writeIncoming(buf);
ssl->writeIncoming(buf);
}
void server_handleConnection()
{
// Note: only 1 connection supported at a time in this example!
if(mode != Idle) {
QTcpSocket* tmp = server->nextPendingConnection();
tmp->close();
connect(tmp, SIGNAL(disconnected()), tmp, SLOT(deleteLater()));
qDebug() << "throwing away extra connection";
return;
}
mode = Handshaking;
sock = server->nextPendingConnection();
connect(sock, SIGNAL(readyRead()), SLOT(sock_readyRead()));
connect(sock, SIGNAL(disconnected()), SLOT(sock_disconnected()));
connect(sock, SIGNAL(error(QAbstractSocket::SocketError)),
SLOT(sock_error(QAbstractSocket::SocketError)));
connect(sock, SIGNAL(bytesWritten(qint64)), SLOT(sock_bytesWritten(qint64)));
// Note: only 1 connection supported at a time in this example!
if (mode != Idle) {
QTcpSocket *tmp = server->nextPendingConnection();
tmp->close();
connect(tmp, &QTcpSocket::disconnected, tmp, &QTcpSocket::deleteLater);
qDebug() << "throwing away extra connection";
return;
}
mode = Handshaking;
sock = server->nextPendingConnection();
connect(sock, &QTcpSocket::readyRead, this, &SecureServer::sock_readyRead);
connect(sock, &QTcpSocket::disconnected, this, &SecureServer::sock_disconnected);
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
connect(sock, &QTcpSocket::errorOccurred, this, &SecureServer::sock_error);
#else
connect(sock, QOverload<QAbstractSocket::SocketError>::of(&QTcpSocket::error), this, &SecureServer::sock_error);
#endif
connect(sock, &QTcpSocket::bytesWritten, this, &SecureServer::sock_bytesWritten);
qDebug() << "Connection received! Starting TLS handshake.";
ssl->setCertificate(cert, privkey);
ssl->startServer();
qDebug() << "Connection received! Starting TLS handshake.";
ssl->setCertificate(cert, privkey);
ssl->startServer();
}
void sock_disconnected()
{
qDebug() << "Connection closed.";
qDebug() << "Connection closed.";
}
void sock_bytesWritten(qint64 x)
{
if(mode == Active && sent) {
qint64 bytes = ssl->convertBytesWritten(x);
bytesLeft -= bytes;
if (mode == Active && sent) {
qint64 bytes = ssl->convertBytesWritten(x);
bytesLeft -= bytes;
if(bytesLeft == 0) {
mode = Closing;
qDebug() << "Data transfer complete - SSL shutting down";
ssl->close();
}
}
if (bytesLeft == 0) {
mode = Closing;
qDebug() << "Data transfer complete - SSL shutting down";
ssl->close();
}
}
}
void sock_error(QAbstractSocket::SocketError error)
{
qDebug() << "Socket error: " << (unsigned) error;
qDebug() << "Socket error: " << (unsigned)error;
}
void ssl_handshaken()
{
qDebug() << "Successful SSL handshake. Waiting for newline.";
bytesLeft = 0;
sent = false;
mode = Active;
ssl->continueAfterStep();
qDebug() << "Successful SSL handshake. Waiting for newline.";
bytesLeft = 0;
sent = false;
mode = Active;
ssl->continueAfterStep();
}
void ssl_readyRead()
{
QByteArray a = ssl->read();
QByteArray b =
"<html>\n"
"<head><title>Test</title></head>\n"
"<body>this is only a test</body>\n"
"</html>\n";
ssl->read();
QByteArray b =
"<html>\n"
"<head><title>Test</title></head>\n"
"<body>this is only a test</body>\n"
"</html>\n";
qDebug() << "Sending test response.";
sent = true;
ssl->write(b);
qDebug() << "Sending test response.";
sent = true;
ssl->write(b);
}
void ssl_readyReadOutgoing()
{
int plainBytes;
QByteArray outgoingData = ssl->readOutgoing(&plainBytes);
sock->write( outgoingData );
int plainBytes;
QByteArray outgoingData = ssl->readOutgoing(&plainBytes);
sock->write(outgoingData);
}
void ssl_closed()
{
qDebug() << "Closing socket.";
sock->close();
mode = Idle;
qDebug() << "Closing socket.";
sock->close();
mode = Idle;
}
void ssl_error()
{
if(ssl->errorCode() == QCA::TLS::ErrorHandshake) {
qDebug() << "SSL Handshake Error! Closing.";
sock->close();
}
else {
qDebug() << "SSL Error! Closing.";
sock->close();
}
mode = Idle;
if (ssl->errorCode() == QCA::TLS::ErrorHandshake) {
qDebug() << "SSL Handshake Error! Closing.";
sock->close();
} else {
qDebug() << "SSL Error! Closing.";
sock->close();
}
mode = Idle;
}
private:
quint16 port;
QTcpServer *server;
QTcpSocket *sock;
QCA::TLS *ssl;
quint16 port;
QTcpServer * server;
QTcpSocket * sock;
QCA::TLS * ssl;
QCA::Certificate cert;
QCA::PrivateKey privkey;
QCA::PrivateKey privkey;
bool sent;
int mode;
bool sent;
int mode;
qint64 bytesLeft;
};
@ -256,15 +265,15 @@ int main(int argc, char **argv)
QCA::Initializer init;
QCoreApplication app(argc, argv);
int port = argc > 1 ? QString(argv[1]).toInt() : 8000;
int port = argc > 1 ? QString::fromLatin1(argv[1]).toInt() : 8000;
if(!QCA::isSupported("tls")) {
qDebug() << "TLS not supported!";
return 1;
if (!QCA::isSupported("tls")) {
qDebug() << "TLS not supported!";
return 1;
}
SecureServer *server = new SecureServer(port);
QObject::connect(server, SIGNAL(quit()), &app, SLOT(quit()));
QObject::connect(server, &SecureServer::quit, &app, &QCoreApplication::quit);
server->start();
app.exec();
delete server;

View File

@ -1,8 +1,10 @@
set(ssltest_bin_SRCS ssltest.cpp)
MY_AUTOMOC( ssltest_bin_SRCS)
add_executable(ssltest ${ssltest_bin_SRCS})
target_link_qca_libraries(ssltest)
target_link_libraries(ssltest ${QT_QTNETWORK_LIBRARY})
if(QT6)
target_link_libraries(ssltest Qt6::Network)
else()
target_link_libraries(ssltest Qt5::Network)
endif()

View File

@ -29,308 +29,303 @@
#endif
char exampleCA_cert[] =
"-----BEGIN CERTIFICATE-----\n"
"MIICSzCCAbSgAwIBAgIBADANBgkqhkiG9w0BAQUFADA4MRMwEQYDVQQDEwpFeGFt\n"
"cGxlIENBMQswCQYDVQQGEwJVUzEUMBIGA1UEChMLRXhhbXBsZSBPcmcwHhcNMDYw\n"
"MzE1MDY1ODMyWhcNMDYwNDE1MDY1ODMyWjA4MRMwEQYDVQQDEwpFeGFtcGxlIENB\n"
"MQswCQYDVQQGEwJVUzEUMBIGA1UEChMLRXhhbXBsZSBPcmcwgZ8wDQYJKoZIhvcN\n"
"AQEBBQADgY0AMIGJAoGBAL6ULdOxmpeZ+G/ypV12eNO4qnHSVIPTrYPkQuweXqPy\n"
"atwGFheG+hLVsNIh9GGOS0tCe7a3hBBKN0BJg1ppfk2x39cDx7hefYqjBuZvp/0O\n"
"8Ja3qlQiJLezITZKLxMBrsibcvcuH8zpfUdys2yaN+YGeqNfjQuoNN3Byl1TwuGJ\n"
"AgMBAAGjZTBjMB0GA1UdDgQWBBSQKCUCLNM7uKrAt5o7qv/yQm6qEzASBgNVHRMB\n"
"Af8ECDAGAQEBAgEIMB4GA1UdEQQXMBWBE2V4YW1wbGVAZXhhbXBsZS5jb20wDgYD\n"
"VR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBBQUAA4GBAAh+SIeT1Ao5qInw8oMSoTdO\n"
"lQ6h67ec/Jk5KmK4OoskuimmHI0Sp0C5kOCLehXbsVWW8pXsNC2fv0d2HkdaSUcX\n"
"hwLzqgyZXd4mupIYlaOTZhuHDwWPCAOZS4LVsi2tndTRHKCP12441JjNKhmZRhkR\n"
"u5zzD60nWgM9dKTaxuZM\n"
"-----END CERTIFICATE-----\n";
"-----BEGIN CERTIFICATE-----\n"
"MIICSzCCAbSgAwIBAgIBADANBgkqhkiG9w0BAQUFADA4MRMwEQYDVQQDEwpFeGFt\n"
"cGxlIENBMQswCQYDVQQGEwJVUzEUMBIGA1UEChMLRXhhbXBsZSBPcmcwHhcNMDYw\n"
"MzE1MDY1ODMyWhcNMDYwNDE1MDY1ODMyWjA4MRMwEQYDVQQDEwpFeGFtcGxlIENB\n"
"MQswCQYDVQQGEwJVUzEUMBIGA1UEChMLRXhhbXBsZSBPcmcwgZ8wDQYJKoZIhvcN\n"
"AQEBBQADgY0AMIGJAoGBAL6ULdOxmpeZ+G/ypV12eNO4qnHSVIPTrYPkQuweXqPy\n"
"atwGFheG+hLVsNIh9GGOS0tCe7a3hBBKN0BJg1ppfk2x39cDx7hefYqjBuZvp/0O\n"
"8Ja3qlQiJLezITZKLxMBrsibcvcuH8zpfUdys2yaN+YGeqNfjQuoNN3Byl1TwuGJ\n"
"AgMBAAGjZTBjMB0GA1UdDgQWBBSQKCUCLNM7uKrAt5o7qv/yQm6qEzASBgNVHRMB\n"
"Af8ECDAGAQEBAgEIMB4GA1UdEQQXMBWBE2V4YW1wbGVAZXhhbXBsZS5jb20wDgYD\n"
"VR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBBQUAA4GBAAh+SIeT1Ao5qInw8oMSoTdO\n"
"lQ6h67ec/Jk5KmK4OoskuimmHI0Sp0C5kOCLehXbsVWW8pXsNC2fv0d2HkdaSUcX\n"
"hwLzqgyZXd4mupIYlaOTZhuHDwWPCAOZS4LVsi2tndTRHKCP12441JjNKhmZRhkR\n"
"u5zzD60nWgM9dKTaxuZM\n"
"-----END CERTIFICATE-----\n";
void showCertInfo(const QCA::Certificate &cert)
{
printf("-- Cert --\n");
printf(" CN: %s\n", qPrintable(cert.commonName()));
printf(" Valid from: %s, until %s\n",
qPrintable(cert.notValidBefore().toString()),
qPrintable(cert.notValidAfter().toString()));
printf(" PEM:\n%s\n", qPrintable(cert.toPEM()));
printf("-- Cert --\n");
printf(" CN: %s\n", qPrintable(cert.commonName()));
printf(" Valid from: %s, until %s\n",
qPrintable(cert.notValidBefore().toString()),
qPrintable(cert.notValidAfter().toString()));
printf(" PEM:\n%s\n", qPrintable(cert.toPEM()));
}
static QString validityToString(QCA::Validity v)
{
QString s;
switch(v)
{
case QCA::ValidityGood:
s = "Validated";
break;
case QCA::ErrorRejected:
s = "Root CA is marked to reject the specified purpose";
break;
case QCA::ErrorUntrusted:
s = "Certificate not trusted for the required purpose";
break;
case QCA::ErrorSignatureFailed:
s = "Invalid signature";
break;
case QCA::ErrorInvalidCA:
s = "Invalid CA certificate";
break;
case QCA::ErrorInvalidPurpose:
s = "Invalid certificate purpose";
break;
case QCA::ErrorSelfSigned:
s = "Certificate is self-signed";
break;
case QCA::ErrorRevoked:
s = "Certificate has been revoked";
break;
case QCA::ErrorPathLengthExceeded:
s = "Maximum certificate chain length exceeded";
break;
case QCA::ErrorExpired:
s = "Certificate has expired";
break;
case QCA::ErrorExpiredCA:
s = "CA has expired";
break;
case QCA::ErrorValidityUnknown:
default:
s = "General certificate validation error";
break;
}
return s;
QString s;
switch (v) {
case QCA::ValidityGood:
s = QStringLiteral("Validated");
break;
case QCA::ErrorRejected:
s = QStringLiteral("Root CA is marked to reject the specified purpose");
break;
case QCA::ErrorUntrusted:
s = QStringLiteral("Certificate not trusted for the required purpose");
break;
case QCA::ErrorSignatureFailed:
s = QStringLiteral("Invalid signature");
break;
case QCA::ErrorInvalidCA:
s = QStringLiteral("Invalid CA certificate");
break;
case QCA::ErrorInvalidPurpose:
s = QStringLiteral("Invalid certificate purpose");
break;
case QCA::ErrorSelfSigned:
s = QStringLiteral("Certificate is self-signed");
break;
case QCA::ErrorRevoked:
s = QStringLiteral("Certificate has been revoked");
break;
case QCA::ErrorPathLengthExceeded:
s = QStringLiteral("Maximum certificate chain length exceeded");
break;
case QCA::ErrorExpired:
s = QStringLiteral("Certificate has expired");
break;
case QCA::ErrorExpiredCA:
s = QStringLiteral("CA has expired");
break;
case QCA::ErrorValidityUnknown:
default:
s = QStringLiteral("General certificate validation error");
break;
}
return s;
}
class SecureTest : public QObject
{
Q_OBJECT
Q_OBJECT
public:
SecureTest()
{
sock_done = false;
ssl_done = false;
SecureTest()
{
sock_done = false;
ssl_done = false;
sock = new QTcpSocket;
connect(sock, SIGNAL(connected()), SLOT(sock_connected()));
connect(sock, SIGNAL(readyRead()), SLOT(sock_readyRead()));
connect(sock, SIGNAL(error(QAbstractSocket::SocketError)),
SLOT(sock_error(QAbstractSocket::SocketError)));
sock = new QTcpSocket;
connect(sock, &QTcpSocket::connected, this, &SecureTest::sock_connected);
connect(sock, &QTcpSocket::readyRead, this, &SecureTest::sock_readyRead);
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
connect(sock, &QTcpSocket::errorOccurred, this, &SecureTest::sock_error);
#else
connect(sock, QOverload<QAbstractSocket::SocketError>::of(&QTcpSocket::error), this, &SecureTest::sock_error);
#endif
ssl = new QCA::TLS;
connect(ssl, SIGNAL(certificateRequested()), SLOT(ssl_certificateRequested()));
connect(ssl, SIGNAL(handshaken()), SLOT(ssl_handshaken()));
connect(ssl, SIGNAL(readyRead()), SLOT(ssl_readyRead()));
connect(ssl, SIGNAL(readyReadOutgoing()),
SLOT(ssl_readyReadOutgoing()));
connect(ssl, SIGNAL(closed()), SLOT(ssl_closed()));
connect(ssl, SIGNAL(error()), SLOT(ssl_error()));
}
ssl = new QCA::TLS;
connect(ssl, &QCA::TLS::certificateRequested, this, &SecureTest::ssl_certificateRequested);
connect(ssl, &QCA::TLS::handshaken, this, &SecureTest::ssl_handshaken);
connect(ssl, &QCA::TLS::readyRead, this, &SecureTest::ssl_readyRead);
connect(ssl, &QCA::TLS::readyReadOutgoing, this, &SecureTest::ssl_readyReadOutgoing);
connect(ssl, &QCA::TLS::closed, this, &SecureTest::ssl_closed);
connect(ssl, &QCA::TLS::error, this, &SecureTest::ssl_error);
}
~SecureTest()
{
delete ssl;
delete sock;
}
~SecureTest() override
{
delete ssl;
delete sock;
}
void start(const QString &_host)
{
int n = _host.indexOf(':');
int port;
if(n != -1)
{
host = _host.mid(0, n);
port = _host.mid(n+1).toInt();
}
else
{
host = _host;
port = 443;
}
void start(const QString &_host)
{
int n = _host.indexOf(QLatin1Char(':'));
int port;
if (n != -1) {
host = _host.mid(0, n);
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
port = QStringView(_host).mid(n + 1).toInt();
#else
port = _host.midRef(n + 1).toInt();
#endif
} else {
host = _host;
port = 443;
}
printf("Trying %s:%d...\n", qPrintable(host), port);
sock->connectToHost(host, port);
}
printf("Trying %s:%d...\n", qPrintable(host), port);
sock->connectToHost(host, port);
}
signals:
void quit();
Q_SIGNALS:
void quit();
private slots:
void sock_connected()
{
// We just do this to help doxygen...
QCA::TLS *ssl = SecureTest::ssl;
private Q_SLOTS:
void sock_connected()
{
// We just do this to help doxygen...
QCA::TLS *ssl = SecureTest::ssl;
printf("Connected, starting TLS handshake...\n");
printf("Connected, starting TLS handshake...\n");
QCA::CertificateCollection rootCerts = QCA::systemStore();
QCA::CertificateCollection rootCerts = QCA::systemStore();
// We add this one to show how, and to make it work with
// the server example.
rootCerts.addCertificate(QCA::Certificate::fromPEM(exampleCA_cert));
// We add this one to show how, and to make it work with
// the server example.
rootCerts.addCertificate(QCA::Certificate::fromPEM(QString::fromLatin1(exampleCA_cert)));
if(!QCA::haveSystemStore())
printf("Warning: no root certs\n");
else
ssl->setTrustedCertificates(rootCerts);
if (!QCA::haveSystemStore())
printf("Warning: no root certs\n");
else
ssl->setTrustedCertificates(rootCerts);
ssl->startClient(host);
}
ssl->startClient(host);
}
void sock_readyRead()
{
// We just do this to help doxygen...
QCA::TLS *ssl = SecureTest::ssl;
void sock_readyRead()
{
// We just do this to help doxygen...
QCA::TLS *ssl = SecureTest::ssl;
ssl->writeIncoming(sock->readAll());
}
ssl->writeIncoming(sock->readAll());
}
void sock_connectionClosed()
{
printf("\nConnection closed.\n");
sock_done = true;
void sock_connectionClosed()
{
printf("\nConnection closed.\n");
sock_done = true;
if(ssl_done && sock_done)
emit quit();
}
if (ssl_done && sock_done)
emit quit();
}
void sock_error(QAbstractSocket::SocketError x)
{
if(x == QAbstractSocket::RemoteHostClosedError)
{
sock_connectionClosed();
return;
}
void sock_error(QAbstractSocket::SocketError x)
{
if (x == QAbstractSocket::RemoteHostClosedError) {
sock_connectionClosed();
return;
}
printf("\nSocket error.\n");
emit quit();
}
printf("\nSocket error.\n");
emit quit();
}
void ssl_handshaken()
{
// We just do this to help doxygen...
QCA::TLS *ssl = SecureTest::ssl;
void ssl_handshaken()
{
// We just do this to help doxygen...
QCA::TLS *ssl = SecureTest::ssl;
QCA::TLS::IdentityResult r = ssl->peerIdentityResult();
QCA::TLS::IdentityResult r = ssl->peerIdentityResult();
printf("Successful SSL handshake using %s (%i of %i bits)\n",
qPrintable(ssl->cipherSuite()),
ssl->cipherBits(),
ssl->cipherMaxBits() );
if(r != QCA::TLS::NoCertificate)
{
cert = ssl->peerCertificateChain().primary();
if(!cert.isNull())
showCertInfo(cert);
}
printf("Successful SSL handshake using %s (%i of %i bits)\n",
qPrintable(ssl->cipherSuite()),
ssl->cipherBits(),
ssl->cipherMaxBits());
if (r != QCA::TLS::NoCertificate) {
cert = ssl->peerCertificateChain().primary();
if (!cert.isNull())
showCertInfo(cert);
}
QString str = "Peer Identity: ";
if(r == QCA::TLS::Valid)
str += "Valid";
else if(r == QCA::TLS::HostMismatch)
str += "Error: Wrong certificate";
else if(r == QCA::TLS::InvalidCertificate)
str += "Error: Invalid certificate.\n -> Reason: " +
validityToString(ssl->peerCertificateValidity());
else
str += "Error: No certificate";
printf("%s\n", qPrintable(str));
QString str = QStringLiteral("Peer Identity: ");
if (r == QCA::TLS::Valid)
str += QStringLiteral("Valid");
else if (r == QCA::TLS::HostMismatch)
str += QStringLiteral("Error: Wrong certificate");
else if (r == QCA::TLS::InvalidCertificate)
str += QStringLiteral("Error: Invalid certificate.\n -> Reason: ") +
validityToString(ssl->peerCertificateValidity());
else
str += QStringLiteral("Error: No certificate");
printf("%s\n", qPrintable(str));
ssl->continueAfterStep();
ssl->continueAfterStep();
printf("Let's try a GET request now.\n");
QString req = "GET / HTTP/1.0\nHost: " + host + "\n\n";
ssl->write(req.toLatin1());
}
printf("Let's try a GET request now.\n");
QString req = QStringLiteral("GET / HTTP/1.0\nHost: ") + host + QStringLiteral("\n\n");
ssl->write(req.toLatin1());
}
void ssl_certificateRequested()
{
// We just do this to help doxygen...
QCA::TLS *ssl = SecureTest::ssl;
void ssl_certificateRequested()
{
// We just do this to help doxygen...
QCA::TLS *ssl = SecureTest::ssl;
printf("Server requested client certificate.\n");
QList<QCA::CertificateInfoOrdered> issuerList = ssl->issuerList();
if(!issuerList.isEmpty())
{
printf("Allowed issuers:\n");
foreach(QCA::CertificateInfoOrdered i, issuerList)
printf(" %s\n", qPrintable(i.toString()));
}
printf("Server requested client certificate.\n");
QList<QCA::CertificateInfoOrdered> issuerList = ssl->issuerList();
if (!issuerList.isEmpty()) {
printf("Allowed issuers:\n");
foreach (QCA::CertificateInfoOrdered i, issuerList)
printf(" %s\n", qPrintable(i.toString()));
}
ssl->continueAfterStep();
}
ssl->continueAfterStep();
}
void ssl_readyRead()
{
// We just do this to help doxygen...
QCA::TLS *ssl = SecureTest::ssl;
void ssl_readyRead()
{
// We just do this to help doxygen...
QCA::TLS *ssl = SecureTest::ssl;
QByteArray a = ssl->read();
printf("%s", a.data());
}
QByteArray a = ssl->read();
printf("%s", a.data());
}
void ssl_readyReadOutgoing()
{
// We just do this to help doxygen...
QCA::TLS *ssl = SecureTest::ssl;
void ssl_readyReadOutgoing()
{
// We just do this to help doxygen...
QCA::TLS *ssl = SecureTest::ssl;
sock->write(ssl->readOutgoing());
}
sock->write(ssl->readOutgoing());
}
void ssl_closed()
{
printf("SSL session closed.\n");
ssl_done = true;
void ssl_closed()
{
printf("SSL session closed.\n");
ssl_done = true;
if(ssl_done && sock_done)
emit quit();
}
if (ssl_done && sock_done)
emit quit();
}
void ssl_error()
{
// We just do this to help doxygen...
QCA::TLS *ssl = SecureTest::ssl;
void ssl_error()
{
// We just do this to help doxygen...
QCA::TLS *ssl = SecureTest::ssl;
int x = ssl->errorCode();
if(x == QCA::TLS::ErrorHandshake)
{
printf("SSL Handshake Error!\n");
emit quit();
}
else
{
printf("SSL Error!\n");
emit quit();
}
}
int x = ssl->errorCode();
if (x == QCA::TLS::ErrorHandshake) {
printf("SSL Handshake Error!\n");
emit quit();
} else {
printf("SSL Error!\n");
emit quit();
}
}
private:
QString host;
QTcpSocket *sock;
QCA::TLS *ssl;
QCA::Certificate cert;
bool sock_done, ssl_done;
QString host;
QTcpSocket * sock;
QCA::TLS * ssl;
QCA::Certificate cert;
bool sock_done, ssl_done;
};
#include "ssltest.moc"
int main(int argc, char **argv)
{
QCA::Initializer init;
QCA::Initializer init;
QCoreApplication app(argc, argv);
QString host = argc > 1 ? argv[1] : "andbit.net";
QCoreApplication app(argc, argv);
QString host = argc > 1 ? QString::fromLocal8Bit(argv[1]) : QStringLiteral("andbit.net");
if(!QCA::isSupported("tls"))
{
printf("TLS not supported!\n");
return 1;
}
if (!QCA::isSupported("tls")) {
printf("TLS not supported!\n");
return 1;
}
SecureTest *s = new SecureTest;
QObject::connect(s, SIGNAL(quit()), &app, SLOT(quit()));
s->start(host);
app.exec();
delete s;
SecureTest *s = new SecureTest;
QObject::connect(s, &SecureTest::quit, &app, &QCoreApplication::quit);
s->start(host);
app.exec();
delete s;
return 0;
return 0;
}

View File

@ -1,9 +1,8 @@
set(tlssocket_bin_moc_SRCS tlssocket.cpp)
set(tlssocket_bin_nonmoc_SRCS main.cpp)
MY_AUTOMOC( tlssocket_bin_moc_SRCS)
add_executable(tlssocket ${tlssocket_bin_moc_SRCS} ${tlssocket_bin_nonmoc_SRCS})
add_executable(tlssocket tlssocket.cpp main.cpp)
target_link_qca_libraries(tlssocket)
target_link_libraries(tlssocket ${QT_QTNETWORK_LIBRARY})
if(QT6)
target_link_libraries(tlssocket Qt6::Network)
else()
target_link_libraries(tlssocket Qt5::Network)
endif()

View File

@ -25,14 +25,14 @@
int main(int argc, char **argv)
{
QCA::Initializer init;
QCoreApplication qapp(argc, argv);
QCA::Initializer init;
QCoreApplication qapp(argc, argv);
TLSSocket socket;
socket.connectToHostEncrypted("www.paypal.com", 443);
socket.write("GET / HTTP/1.0\r\n\r\n");
while(socket.waitForReadyRead())
printf("%s", socket.readAll().data());
TLSSocket socket;
socket.connectToHostEncrypted(QStringLiteral("www.paypal.com"), 443);
socket.write("GET / HTTP/1.0\r\n\r\n");
while (socket.waitForReadyRead())
printf("%s", socket.readAll().constData());
return 0;
return 0;
}

View File

@ -27,191 +27,196 @@
class TLSSocket::Private : public QObject
{
Q_OBJECT
Q_OBJECT
public:
TLSSocket *q;
QTcpSocket *sock;
QCA::TLS *tls;
QString host;
bool encrypted;
bool error, done;
QByteArray readbuf, writebuf;
QCA::Synchronizer sync;
bool waiting;
TLSSocket * q;
QTcpSocket * sock;
QCA::TLS * tls;
QString host;
bool encrypted;
bool error, done;
QByteArray readbuf, writebuf;
QCA::Synchronizer sync;
bool waiting;
Private(TLSSocket *_q) : QObject(_q), q(_q), sync(_q)
{
sock = new QTcpSocket(this);
connect(sock, SIGNAL(connected()), SLOT(sock_connected()));
connect(sock, SIGNAL(readyRead()), SLOT(sock_readyRead()));
connect(sock, SIGNAL(bytesWritten(qint64)), SLOT(sock_bytesWritten(qint64)));
connect(sock, SIGNAL(error(QAbstractSocket::SocketError)), SLOT(sock_error(QAbstractSocket::SocketError)));
Private(TLSSocket *_q)
: QObject(_q)
, q(_q)
, sync(_q)
{
sock = new QTcpSocket(this);
connect(sock, &QTcpSocket::connected, this, &TLSSocket::Private::sock_connected);
connect(sock, &QTcpSocket::readyRead, this, &TLSSocket::Private::sock_readyRead);
connect(sock, &QTcpSocket::bytesWritten, this, &TLSSocket::Private::sock_bytesWritten);
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
connect(sock, &QTcpSocket::errorOccurred, this, &TLSSocket::Private::sock_error);
#else
connect(sock,
QOverload<QAbstractSocket::SocketError>::of(&QTcpSocket::error),
this,
&TLSSocket::Private::sock_error);
#endif
tls = new QCA::TLS(this);
connect(tls, SIGNAL(handshaken()), SLOT(tls_handshaken()));
connect(tls, SIGNAL(readyRead()), SLOT(tls_readyRead()));
connect(tls, SIGNAL(readyReadOutgoing()), SLOT(tls_readyReadOutgoing()));
connect(tls, SIGNAL(closed()), SLOT(tls_closed()));
connect(tls, SIGNAL(error()), SLOT(tls_error()));
tls->setTrustedCertificates(QCA::systemStore());
encrypted = false;
error = false;
waiting = false;
done = false;
}
tls = new QCA::TLS(this);
connect(tls, &QCA::TLS::handshaken, this, &TLSSocket::Private::tls_handshaken);
connect(tls, &QCA::TLS::readyRead, this, &TLSSocket::Private::tls_readyRead);
connect(tls, &QCA::TLS::readyReadOutgoing, this, &TLSSocket::Private::tls_readyReadOutgoing);
connect(tls, &QCA::TLS::closed, this, &TLSSocket::Private::tls_closed);
connect(tls, &QCA::TLS::error, this, &TLSSocket::Private::tls_error);
tls->setTrustedCertificates(QCA::systemStore());
encrypted = false;
error = false;
waiting = false;
done = false;
}
bool waitForReadyRead(int msecs)
{
waiting = true;
bool ok = sync.waitForCondition(msecs);
//while(1)
// QCoreApplication::instance()->processEvents();
waiting = false;
if(error || done)
return false;
return ok;
}
bool waitForReadyRead(int msecs)
{
waiting = true;
bool ok = sync.waitForCondition(msecs);
// while(1)
// QCoreApplication::instance()->processEvents();
waiting = false;
if (error || done)
return false;
return ok;
}
private slots:
void sock_connected()
{
//printf("sock connected\n");
tls->startClient(host);
}
private Q_SLOTS:
void sock_connected()
{
// printf("sock connected\n");
tls->startClient(host);
}
void sock_readyRead()
{
//printf("sock ready read\n");
QByteArray buf = sock->readAll();
//printf("%d bytes\n", buf.size());
tls->writeIncoming(buf);
}
void sock_readyRead()
{
// printf("sock ready read\n");
QByteArray buf = sock->readAll();
// printf("%d bytes\n", buf.size());
tls->writeIncoming(buf);
}
void sock_bytesWritten(qint64 x)
{
Q_UNUSED(x);
//printf("sock bytes written: %d\n", (int)x);
}
void sock_bytesWritten(qint64 x)
{
Q_UNUSED(x);
// printf("sock bytes written: %d\n", (int)x);
}
void sock_error(QAbstractSocket::SocketError x)
{
//printf("sock error: %d\n", x);
Q_UNUSED(x);
done = true;
if(waiting)
sync.conditionMet();
}
void sock_error(QAbstractSocket::SocketError x)
{
// printf("sock error: %d\n", x);
Q_UNUSED(x);
done = true;
if (waiting)
sync.conditionMet();
}
void tls_handshaken()
{
//printf("tls handshaken\n");
if(tls->peerIdentityResult() != QCA::TLS::Valid)
{
printf("not valid\n");
sock->abort();
tls->reset();
error = true;
}
else
{
//printf("valid\n");
encrypted = true;
//printf("%d bytes in writebuf\n", writebuf.size());
if(!writebuf.isEmpty())
{
//printf("[%s]\n", writebuf.data());
tls->write(writebuf);
writebuf.clear();
}
}
if(waiting)
sync.conditionMet();
}
void tls_handshaken()
{
// printf("tls handshaken\n");
if (tls->peerIdentityResult() != QCA::TLS::Valid) {
printf("not valid\n");
sock->abort();
tls->reset();
error = true;
} else {
// printf("valid\n");
encrypted = true;
// printf("%d bytes in writebuf\n", writebuf.size());
if (!writebuf.isEmpty()) {
// printf("[%s]\n", writebuf.data());
tls->write(writebuf);
writebuf.clear();
}
}
if (waiting)
sync.conditionMet();
}
void tls_readyRead()
{
//printf("tls ready read\n");
if(waiting)
sync.conditionMet();
}
void tls_readyRead()
{
// printf("tls ready read\n");
if (waiting)
sync.conditionMet();
}
void tls_readyReadOutgoing()
{
//printf("tls ready read outgoing\n");
QByteArray buf = tls->readOutgoing();
//printf("%d bytes\n", buf.size());
sock->write(buf);
}
void tls_readyReadOutgoing()
{
// printf("tls ready read outgoing\n");
QByteArray buf = tls->readOutgoing();
// printf("%d bytes\n", buf.size());
sock->write(buf);
}
void tls_closed()
{
//printf("tls closed\n");
}
void tls_closed()
{
// printf("tls closed\n");
}
void tls_error()
{
//printf("tls error\n");
}
void tls_error()
{
// printf("tls error\n");
}
};
TLSSocket::TLSSocket(QObject *parent)
:QTcpSocket(parent)
: QTcpSocket(parent)
{
d = new Private(this);
d = new Private(this);
}
TLSSocket::~TLSSocket()
{
delete d;
delete d;
}
void TLSSocket::connectToHostEncrypted(const QString &host, quint16 port)
{
d->host = host;
setOpenMode(QIODevice::ReadWrite);
d->sock->connectToHost(host, port);
d->host = host;
setOpenMode(QIODevice::ReadWrite);
d->sock->connectToHost(host, port);
}
QCA::TLS *TLSSocket::tls()
{
return d->tls;
return d->tls;
}
bool TLSSocket::waitForReadyRead(int msecs)
{
/*if(d->readbuf.isEmpty())
return false;
/*if(d->readbuf.isEmpty())
return false;
if(d->tls->bytesAvailable() == 0)
return false;*/
if(d->tls->bytesAvailable() == 0)
return false;*/
return d->waitForReadyRead(msecs);
return d->waitForReadyRead(msecs);
}
qint64 TLSSocket::readData(char *data, qint64 maxlen)
{
if(!d->error)
d->readbuf += d->tls->read();
unsigned char *p = (unsigned char *)d->readbuf.data();
int size = d->readbuf.size();
int readsize = qMin(size, (int)maxlen);
int newsize = size - readsize;
memcpy(data, p, readsize);
memmove(p, p + readsize, newsize);
d->readbuf.resize(newsize);
return readsize;
if (!d->error)
d->readbuf += d->tls->read();
unsigned char *p = (unsigned char *)d->readbuf.data();
int size = d->readbuf.size();
int readsize = qMin(size, (int)maxlen);
int newsize = size - readsize;
memcpy(data, p, readsize);
memmove(p, p + readsize, newsize);
d->readbuf.resize(newsize);
return readsize;
}
qint64 TLSSocket::writeData(const char *data, qint64 len)
{
//printf("write %d bytes\n", (int)len);
QByteArray buf(data, len);
if(d->encrypted)
d->tls->write(buf);
else
d->writebuf += buf;
return len;
// printf("write %d bytes\n", (int)len);
QByteArray buf(data, len);
if (d->encrypted)
d->tls->write(buf);
else
d->writebuf += buf;
return len;
}
#include "tlssocket.moc"

View File

@ -21,29 +21,30 @@
#ifndef TLSSOCKET_H
#include <QtCrypto>
#include <QTcpSocket>
#include <QtCrypto>
class TLSSocket : public QTcpSocket
{
Q_OBJECT
public:
TLSSocket(QObject *parent = 0);
~TLSSocket();
TLSSocket(QObject *parent = nullptr);
~TLSSocket() override;
void connectToHostEncrypted(const QString &host, quint16 port);
QCA::TLS *tls();
void connectToHostEncrypted(const QString &host, quint16 port);
QCA::TLS *tls();
bool waitForReadyRead(int msecs = -1);
bool waitForReadyRead(int msecs = -1) override;
protected:
// from qiodevice
virtual qint64 readData(char *data, qint64 maxlen);
virtual qint64 writeData(const char *data, qint64 len);
// from qiodevice
qint64 readData(char *data, qint64 maxlen) override;
qint64 writeData(const char *data, qint64 len) override;
private:
class Private;
friend class Private;
Private *d;
class Private;
friend class Private;
Private *d;
};
#endif

10
hooks/pre-commit Normal file
View File

@ -0,0 +1,10 @@
#!/usr/bin/env bash
readonly output=$(git clang-format -v --diff)
if [[ "$output" == *"no modified files to format"* ]]; then exit 0; fi
if [[ "$output" == *"clang-format did not modify any files"* ]]; then exit 0; fi
echo "ERROR: you need to run git clang-format on your commit"
echo " git clang-format -f is potentially what you want"
exit 1

View File

@ -33,16 +33,16 @@
#ifndef QCA_H
#define QCA_H
#include "qca_core.h"
#include "qca_textfilter.h"
#include "qca_basic.h"
#include "qca_publickey.h"
#include "qca_cert.h"
#include "qca_core.h"
#include "qca_keystore.h"
#include "qca_publickey.h"
#include "qca_safetimer.h"
#include "qca_securelayer.h"
#include "qca_securemessage.h"
#include "qca_textfilter.h"
#include "qcaprovider.h"
#include "qpipe.h"
#include "qca_safetimer.h"
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -22,7 +22,7 @@
/**
\file qca_export.h
Preprocessor magic to allow export of library symbols.
Preprocessor magic to allow export of library symbols.
This is strictly internal.
@ -37,16 +37,16 @@
#include <QtGlobal>
#ifdef Q_OS_WIN
# ifndef QCA_STATIC
# ifdef QCA_MAKEDLL
# define QCA_EXPORT Q_DECL_EXPORT
# else
# define QCA_EXPORT Q_DECL_IMPORT
# endif
# endif
#ifndef QCA_STATIC
#ifdef QCA_MAKEDLL
#define QCA_EXPORT Q_DECL_EXPORT
#else
#define QCA_EXPORT Q_DECL_IMPORT
#endif
#endif
#endif
#ifndef QCA_EXPORT
# define QCA_EXPORT
#define QCA_EXPORT
#endif
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -32,37 +32,41 @@ namespace QCA {
class QCA_EXPORT SafeTimer : public QObject
{
Q_OBJECT
Q_OBJECT
public:
SafeTimer(QObject *parent = 0);
~SafeTimer();
SafeTimer(QObject *parent = nullptr);
~SafeTimer() override;
int interval() const;
bool isActive() const;
bool isSingleShot() const;
void setInterval(int msec);
void setSingleShot(bool singleShot);
int timerId() const;
int interval() const;
bool isActive() const;
bool isSingleShot() const;
void setInterval(int msec);
void setSingleShot(bool singleShot);
int timerId() const;
public Q_SLOTS:
void start(int msec);
void start();
void stop();
void start(int msec);
void start();
void stop();
Q_SIGNALS:
void timeout();
void timeout();
protected:
bool event(QEvent *event);
void timerEvent(QTimerEvent *event);
bool event(QEvent *event) override;
void timerEvent(QTimerEvent *event) override;
private:
// Functions is used internally. Outer world mustn't have access them.
void startTimer() {}
void killTimer(int) {}
// Functions is used internally. Outer world mustn't have access them.
void startTimer()
{
}
void killTimer(int)
{
}
class Private;
Private *d;
class Private;
Private *d;
};
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -43,7 +43,7 @@ namespace QCA {
Superclass for text based filtering algorithms
This differs from Filter in that it has the concept
of an algorithm that works in two directions, and
of an algorithm that works in two directions, and
supports operations on QString arguments.
\ingroup UserAPI
@ -51,107 +51,107 @@ namespace QCA {
class QCA_EXPORT TextFilter : public Filter
{
public:
/**
Standard constructor
/**
Standard constructor
\param dir the Direction that this TextFilter
should use.
*/
TextFilter(Direction dir);
\param dir the Direction that this TextFilter
should use.
*/
TextFilter(Direction dir);
/**
Reset the TextFilter
/**
Reset the TextFilter
\param dir the Direction that this TextFilter
should use.
*/
void setup(Direction dir);
\param dir the Direction that this TextFilter
should use.
*/
void setup(Direction dir);
/**
The direction the TextFilter is set up to use
*/
Direction direction() const;
/**
The direction the TextFilter is set up to use
*/
Direction direction() const;
/**
Process an array in the "forward" direction,
returning an array
/**
Process an array in the "forward" direction,
returning an array
This method runs in the forward direction, so
for something like a Base64 encoding, it takes
the "native" array, and returns that array
encoded in base64.
This method runs in the forward direction, so
for something like a Base64 encoding, it takes
the "native" array, and returns that array
encoded in base64.
\param a the array to encode
*/
MemoryRegion encode(const MemoryRegion &a);
\param a the array to encode
*/
MemoryRegion encode(const MemoryRegion &a);
/**
Process an array in the "reverse" direction,
returning an array
/**
Process an array in the "reverse" direction,
returning an array
This method runs in the reverse direction, so
for something like a Base64 encoding, it takes
a Base64 encoded array, and returns the "native"
representation.
This method runs in the reverse direction, so
for something like a Base64 encoding, it takes
a Base64 encoded array, and returns the "native"
representation.
\param a the array to decode
*/
MemoryRegion decode(const MemoryRegion &a);
\param a the array to decode
*/
MemoryRegion decode(const MemoryRegion &a);
/**
Process an array in the "forward" direction,
returning a QString
/**
Process an array in the "forward" direction,
returning a QString
This is equivalent to encode(), except
that it returns a QString, rather than a
byte array.
This is equivalent to encode(), except
that it returns a QString, rather than a
byte array.
\param a the array to encode
*/
QString arrayToString(const MemoryRegion &a);
\param a the array to encode
*/
QString arrayToString(const MemoryRegion &a);
/**
Process an string in the "reverse" direction,
returning a byte array
/**
Process an string in the "reverse" direction,
returning a byte array
This is equivalent to decode(), except
that it takes a QString, rather than a
byte array.
This is equivalent to decode(), except
that it takes a QString, rather than a
byte array.
\param s the array to decode
*/
MemoryRegion stringToArray(const QString &s);
\param s the array to decode
*/
MemoryRegion stringToArray(const QString &s);
/**
Process a string in the "forward" direction,
returning a string
/**
Process a string in the "forward" direction,
returning a string
This is equivalent to encode(), except
that it takes and returns a QString, rather than
byte arrays.
This is equivalent to encode(), except
that it takes and returns a QString, rather than
byte arrays.
\param s the string to encode
*/
QString encodeString(const QString &s);
\param s the string to encode
*/
QString encodeString(const QString &s);
/**
Process a string in the "reverse" direction,
returning a string
/**
Process a string in the "reverse" direction,
returning a string
This is equivalent to decode(), except
that it takes and returns a QString, rather than
byte arrays.
This is equivalent to decode(), except
that it takes and returns a QString, rather than
byte arrays.
\param s the string to decode
*/
QString decodeString(const QString &s);
\param s the string to decode
*/
QString decodeString(const QString &s);
protected:
/**
Internal state variable for the Direction
that the filter operates in
*/
Direction _dir;
/**
Internal state variable for the Direction
that the filter operates in
*/
Direction _dir;
};
/**
@ -164,62 +164,62 @@ protected:
class QCA_EXPORT Hex : public TextFilter
{
public:
/**
Standard constructor
/**
Standard constructor
\param dir the Direction that should be used.
\param dir the Direction that should be used.
\note The direction can be changed using
the setup() call.
*/
Hex(Direction dir = Encode);
\note The direction can be changed using
the setup() call.
*/
Hex(Direction dir = Encode);
/**
Reset the internal state.
/**
Reset the internal state.
This is useful to reuse an existing Hex object
*/
virtual void clear();
This is useful to reuse an existing Hex object
*/
void clear() override;
/**
Process more data, returning the corresponding
encoded or decoded (depending on the Direction
set in the constructor or setup() call) representation.
/**
Process more data, returning the corresponding
encoded or decoded (depending on the Direction
set in the constructor or setup() call) representation.
If you find yourself with code that only calls
this method once, you might be better off using
encode() or decode(). Similarly, if the data is
really a string, you might be better off using
arrayToString(), encodeString(), stringToArray()
or decodeString().
If you find yourself with code that only calls
this method once, you might be better off using
encode() or decode(). Similarly, if the data is
really a string, you might be better off using
arrayToString(), encodeString(), stringToArray()
or decodeString().
\param a the array containing data to process
*/
virtual MemoryRegion update(const MemoryRegion &a);
\param a the array containing data to process
*/
MemoryRegion update(const MemoryRegion &a) override;
/**
Complete the algorithm
/**
Complete the algorithm
\return any remaining output. Because of the way
hexadecimal encoding works, this will return a
zero length array - any output will have been returned
from the update() call.
*/
virtual MemoryRegion final();
\return any remaining output. Because of the way
hexadecimal encoding works, this will return a
zero length array - any output will have been returned
from the update() call.
*/
MemoryRegion final() override;
/**
Test if an update() or final() call succeeded.
\return true if the previous call succeeded
*/
virtual bool ok() const;
/**
Test if an update() or final() call succeeded.
\return true if the previous call succeeded
*/
bool ok() const override;
private:
Q_DISABLE_COPY(Hex)
Q_DISABLE_COPY(Hex)
uchar val;
bool partial;
bool _ok;
uchar val;
bool partial;
bool _ok;
};
/**
@ -232,94 +232,94 @@ private:
class QCA_EXPORT Base64 : public TextFilter
{
public:
/**
Standard constructor
/**
Standard constructor
\param dir the Direction that should be used.
\param dir the Direction that should be used.
\note The direction can be changed using
the setup() call.
*/
Base64(Direction dir = Encode);
\note The direction can be changed using
the setup() call.
*/
Base64(Direction dir = Encode);
/**
Returns true if line breaks are enabled
*/
bool lineBreaksEnabled() const;
/**
Returns true if line breaks are enabled
*/
bool lineBreaksEnabled() const;
/**
Returns the line break column
*/
int lineBreaksColumn() const;
/**
Returns the line break column
*/
int lineBreaksColumn() const;
/**
Sets line break mode. If enabled, linebreaks will be
added to encoded output or accepted in encoded input.
If disabled, linebreaks in encoded input will cause
a failure to decode. The default is disabled.
/**
Sets line break mode. If enabled, linebreaks will be
added to encoded output or accepted in encoded input.
If disabled, linebreaks in encoded input will cause
a failure to decode. The default is disabled.
\param b whether to enable line breaks (true) or disable line breaks (false)
*/
void setLineBreaksEnabled(bool b);
\param b whether to enable line breaks (true) or disable line breaks (false)
*/
void setLineBreaksEnabled(bool b);
/**
Sets the column that linebreaks should be inserted at
when encoding.
/**
Sets the column that linebreaks should be inserted at
when encoding.
\param column the column number that line breaks should be inserted at.
*/
void setLineBreaksColumn(int column);
\param column the column number that line breaks should be inserted at.
*/
void setLineBreaksColumn(int column);
/**
Reset the internal state. This is useful to
reuse an existing Base64 object
*/
virtual void clear();
/**
Reset the internal state. This is useful to
reuse an existing Base64 object
*/
void clear() override;
/**
Process more data, returning the corresponding
encoded or decoded (depending on the Direction
set in the constructor or setup() call) representation.
/**
Process more data, returning the corresponding
encoded or decoded (depending on the Direction
set in the constructor or setup() call) representation.
If you find yourself with code that only calls
this method once, you might be better off using
encode() or decode(). Similarly, if the data is
really a string, you might be better off using
arrayToString(), encodeString(), stringToArray()
or decodeString().
If you find yourself with code that only calls
this method once, you might be better off using
encode() or decode(). Similarly, if the data is
really a string, you might be better off using
arrayToString(), encodeString(), stringToArray()
or decodeString().
\param a the array containing data to process
*/
virtual MemoryRegion update(const MemoryRegion &a);
\param a the array containing data to process
*/
MemoryRegion update(const MemoryRegion &a) override;
/**
Complete the algorithm
/**
Complete the algorithm
\return any remaining output. Because of the way
Base64 encoding works, you will get either an
empty array, or an array containing one or two
"=" (equals, 0x3D) characters.
*/
virtual MemoryRegion final();
\return any remaining output. Because of the way
Base64 encoding works, you will get either an
empty array, or an array containing one or two
"=" (equals, 0x3D) characters.
*/
MemoryRegion final() override;
/**
Test if an update() or final() call succeeded.
\return true if the previous call succeeded
*/
virtual bool ok() const;
/**
Test if an update() or final() call succeeded.
\return true if the previous call succeeded
*/
bool ok() const override;
private:
Q_DISABLE_COPY(Base64)
Q_DISABLE_COPY(Base64)
QByteArray partial;
bool _ok;
int col;
bool _lb_enabled;
int _lb_column;
QByteArray partial;
bool _ok;
int col;
bool _lb_enabled;
int _lb_column;
class Private;
Private *d;
class Private;
Private *d;
};
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -34,13 +34,13 @@
#ifndef DOXYGEN_SHOULD_SKIP_THIS
#ifndef QPIPE_NO_SECURE
# define QPIPE_SECURE
#define QPIPE_SECURE
#endif
#ifdef QPIPE_SECURE
# include "QtCrypto"
#include "QtCrypto"
#else
# define QCA_EXPORT
#define QCA_EXPORT
#endif
// defs adapted qprocess_p.h
@ -61,7 +61,6 @@ typedef int Q_PIPE_ID;
namespace QCA {
/**
\class QPipeDevice qpipe.h QtCrypto
@ -74,136 +73,136 @@ namespace QCA {
*/
class QCA_EXPORT QPipeDevice : public QObject
{
Q_OBJECT
Q_OBJECT
public:
/**
The type of device
*/
enum Type
{
Read, ///< The pipe end can be read from
Write ///< The pipe end can be written to
};
/**
The type of device
*/
enum Type
{
Read, ///< The pipe end can be read from
Write ///< The pipe end can be written to
};
/**
Standard constructor
/**
Standard constructor
\param parent the parent object to this object
*/
QPipeDevice(QObject *parent = 0);
~QPipeDevice();
\param parent the parent object to this object
*/
QPipeDevice(QObject *parent = nullptr);
~QPipeDevice() override;
/**
The Type of the pipe device (that is, read or write)
*/
Type type() const;
/**
The Type of the pipe device (that is, read or write)
*/
Type type() const;
/**
Test whether this object corresponds to a valid pipe
*/
bool isValid() const;
/**
Test whether this object corresponds to a valid pipe
*/
bool isValid() const;
/**
The low level identification for this pipe.
/**
The low level identification for this pipe.
On Windows, this is a HANDLE. On Unix, this is a file descriptor (i.e. integer).
On Windows, this is a HANDLE. On Unix, this is a file descriptor (i.e. integer).
Code using this method should be carefully tested for portability.
Code using this method should be carefully tested for portability.
\sa idAsInt
*/
Q_PIPE_ID id() const;
\sa idAsInt
*/
Q_PIPE_ID id() const;
/**
The low level identification for this pipe, returned as an integer.
/**
The low level identification for this pipe, returned as an integer.
Code using this method should be carefully tested for portability.
Code using this method should be carefully tested for portability.
\sa id().
*/
int idAsInt() const;
\sa id().
*/
int idAsInt() const;
/**
Take over an existing pipe id, closing the old pipe if any.
/**
Take over an existing pipe id, closing the old pipe if any.
\param id the identification of the pipe end to take over.
\param t the type of pipe end (read or write).
*/
void take(Q_PIPE_ID id, Type t);
\param id the identification of the pipe end to take over.
\param t the type of pipe end (read or write).
*/
void take(Q_PIPE_ID id, Type t);
/**
Enable the pipe for reading or writing (depending on Type)
*/
void enable();
/**
Enable the pipe for reading or writing (depending on Type)
*/
void enable();
/**
Close the pipe end.
*/
void close();
/**
Close the pipe end.
*/
void close();
/**
Release the pipe end, but do not close it.
*/
void release();
/**
Release the pipe end, but do not close it.
*/
void release();
/**
Set the pipe end to be inheritable
/**
Set the pipe end to be inheritable
\note On Windows, this operation changes the pipe end id value.
\note On Windows, this operation changes the pipe end id value.
\param enabled whether the pipe is inheritable (true) or not (false)
*/
bool setInheritable(bool enabled);
\param enabled whether the pipe is inheritable (true) or not (false)
*/
bool setInheritable(bool enabled);
/**
Obtain the number of bytes available to be read.
*/
int bytesAvailable() const;
/**
Obtain the number of bytes available to be read.
*/
int bytesAvailable() const;
/**
Read from the pipe end
/**
Read from the pipe end
\param data where to put the data that has been read
\param maxsize the maximum number of bytes to be read.
\param data where to put the data that has been read
\param maxsize the maximum number of bytes to be read.
\return the actual number of bytes read, 0 on end-of-file, or -1 on error.
*/
int read(char *data, int maxsize);
\return the actual number of bytes read, 0 on end-of-file, or -1 on error.
*/
int read(char *data, int maxsize);
/**
Write to the pipe end.
/**
Write to the pipe end.
\param data the source of the data to be written
\param size the number of bytes in the data to be written
\param data the source of the data to be written
\param size the number of bytes in the data to be written
\note the data source must remain valid
\note the data source must remain valid
\return the number of bytes written, or -1 on error.
*/
int write(const char *data, int size);
\return the number of bytes written, or -1 on error.
*/
int write(const char *data, int size);
/**
The result of a write operation
/**
The result of a write operation
\param written if not null, this will be set to the number of
bytes written in the last operation.
\param written if not null, this will be set to the number of
bytes written in the last operation.
\return 0 on success (all data written), or -1 on error
*/
int writeResult(int *written) const;
\return 0 on success (all data written), or -1 on error
*/
int writeResult(int *written) const;
Q_SIGNALS:
/**
Emitted when the pipe end can be read from or written to (depending on its Type).
*/
void notify();
/**
Emitted when the pipe end can be read from or written to (depending on its Type).
*/
void notify();
private:
Q_DISABLE_COPY(QPipeDevice)
Q_DISABLE_COPY(QPipeDevice)
class Private;
friend class Private;
Private *d;
class Private;
friend class Private;
Private *d;
};
/**
@ -217,248 +216,247 @@ private:
*/
class QCA_EXPORT QPipeEnd : public QObject
{
Q_OBJECT
Q_OBJECT
public:
/**
The type of error
*/
enum Error
{
ErrorEOF, ///< End of file error
ErrorBroken ///< Broken pipe error
};
/**
The type of error
*/
enum Error
{
ErrorEOF, ///< End of file error
ErrorBroken ///< Broken pipe error
};
/**
Standard constructor
/**
Standard constructor
\param parent the parent object for this object
*/
QPipeEnd(QObject *parent = nullptr);
\param parent the parent object for this object
*/
QPipeEnd(QObject *parent = 0);
~QPipeEnd() override;
~QPipeEnd();
/**
Reset the pipe end to an inactive state
*/
void reset();
/**
Reset the pipe end to an inactive state
*/
void reset();
/**
The type of pipe end (either read or write)
*/
QPipeDevice::Type type() const;
/**
The type of pipe end (either read or write)
*/
QPipeDevice::Type type() const;
/**
Determine whether the pipe end is valid.
/**
Determine whether the pipe end is valid.
\note This does not mean the pipe is ready to be used - you
may need to call enable() first
*/
bool isValid() const;
\note This does not mean the pipe is ready to be used - you
may need to call enable() first
*/
bool isValid() const;
/**
Pipe identification
*/
Q_PIPE_ID id() const;
/**
Pipe identification
*/
Q_PIPE_ID id() const;
/**
Pipe identification
*/
int idAsInt() const;
/**
Pipe identification
*/
int idAsInt() const;
/**
Take over an existing pipe handle
/**
Take over an existing pipe handle
\param id the pipe handle
\param t the type of the pipe (read or write)
*/
void take(Q_PIPE_ID id, QPipeDevice::Type t);
\param id the pipe handle
\param t the type of the pipe (read or write)
*/
void take(Q_PIPE_ID id, QPipeDevice::Type t);
#ifdef QPIPE_SECURE
/**
Sets whether the pipe uses secure memory for read/write
/**
Sets whether the pipe uses secure memory for read/write
Enabling this may reduce performance, and it should only be used if
sensitive data is being transmitted (such as a passphrase).
Enabling this may reduce performance, and it should only be used if
sensitive data is being transmitted (such as a passphrase).
\param secure whether the pipe uses secure memory (true) or not (false).
*/
void setSecurityEnabled(bool secure);
\param secure whether the pipe uses secure memory (true) or not (false).
*/
void setSecurityEnabled(bool secure);
#endif
/**
Enable the endpoint for the pipe
/**
Enable the endpoint for the pipe
When an endpoint is created, it is not
able to be used until it is enabled.
*/
void enable();
When an endpoint is created, it is not
able to be used until it is enabled.
*/
void enable();
/**
Close the end of the pipe
/**
Close the end of the pipe
\sa closed()
*/
void close();
\sa closed()
*/
void close();
/**
Let go of the active pipe handle, but don't close it
/**
Let go of the active pipe handle, but don't close it
Use this before destructing QPipeEnd, if you don't want the pipe
to automatically close.
*/
void release();
Use this before destructing QPipeEnd, if you don't want the pipe
to automatically close.
*/
void release();
/**
Sets whether the pipe should be inheritable to child processes
/**
Sets whether the pipe should be inheritable to child processes
Returns true if inheritability was successfully changed, otherwise
false.
Returns true if inheritability was successfully changed, otherwise
false.
\param enabled whether the pipe is inheritable (true) or not (false).
*/
bool setInheritable(bool enabled);
\param enabled whether the pipe is inheritable (true) or not (false).
*/
bool setInheritable(bool enabled);
/**
Clear the contents of the pipe, and invalidate the pipe
*/
void finalize();
/**
Clear the contents of the pipe, and invalidate the pipe
*/
void finalize();
/**
Clear the contents of the pipe, and release the pipe
*/
void finalizeAndRelease();
/**
Clear the contents of the pipe, and release the pipe
*/
void finalizeAndRelease();
/**
Determine how many bytes are available to be read.
/**
Determine how many bytes are available to be read.
This only makes sense at the read end of the pipe
This only makes sense at the read end of the pipe
\sa readyRead() for a signal that can be used to determine
when there are bytes available to read.
*/
int bytesAvailable() const;
\sa readyRead() for a signal that can be used to determine
when there are bytes available to read.
*/
int bytesAvailable() const;
/**
Returns the number of bytes pending to write
/**
Returns the number of bytes pending to write
This only makes sense at the write end of the pipe
This only makes sense at the write end of the pipe
\sa bytesWritten() for a signal that can be used to determine
when bytes have been written
*/
int bytesToWrite() const;
\sa bytesWritten() for a signal that can be used to determine
when bytes have been written
*/
int bytesToWrite() const;
/**
Read bytes from the pipe.
/**
Read bytes from the pipe.
You can only call this on the read end of the pipe
You can only call this on the read end of the pipe
If the pipe is using secure memory, you should use readSecure()
If the pipe is using secure memory, you should use readSecure()
\param bytes the number of bytes to read (-1 for all
content).
*/
QByteArray read(int bytes = -1);
\param bytes the number of bytes to read (-1 for all
content).
*/
QByteArray read(int bytes = -1);
/**
Write bytes to the pipe.
/**
Write bytes to the pipe.
You can only call this on the write end of the pipe.
You can only call this on the write end of the pipe.
If the pipe is using secure memory, you should use writeSecure().
If the pipe is using secure memory, you should use writeSecure().
\param a the array to write to the pipe
*/
void write(const QByteArray &a);
\param a the array to write to the pipe
*/
void write(const QByteArray &a);
#ifdef QPIPE_SECURE
/**
Read bytes from the pipe.
/**
Read bytes from the pipe.
You can only call this on the read end of the pipe
You can only call this on the read end of the pipe
If the pipe is using insecure memory, you should use read()
If the pipe is using insecure memory, you should use read()
\param bytes the number of bytes to read (-1 for all
content).
*/
SecureArray readSecure(int bytes = -1);
\param bytes the number of bytes to read (-1 for all
content).
*/
SecureArray readSecure(int bytes = -1);
/**
Write bytes to the pipe.
/**
Write bytes to the pipe.
You can only call this on the write end of the pipe.
You can only call this on the write end of the pipe.
If the pipe is using insecure memory, you should use write().
If the pipe is using insecure memory, you should use write().
\param a the array to write to the pipe
*/
void writeSecure(const SecureArray &a);
\param a the array to write to the pipe
*/
void writeSecure(const SecureArray &a);
#endif
/**
Returns any unsent bytes queued for writing
/**
Returns any unsent bytes queued for writing
If the pipe is using secure memory, you should use
takeBytesToWriteSecure().
*/
QByteArray takeBytesToWrite();
If the pipe is using secure memory, you should use
takeBytesToWriteSecure().
*/
QByteArray takeBytesToWrite();
#ifdef QPIPE_SECURE
/**
Returns any unsent bytes queued for writing
/**
Returns any unsent bytes queued for writing
If the pipe is using insecure memory, you should use
takeBytesToWrite().
*/
SecureArray takeBytesToWriteSecure();
If the pipe is using insecure memory, you should use
takeBytesToWrite().
*/
SecureArray takeBytesToWriteSecure();
#endif
Q_SIGNALS:
/**
Emitted when there are bytes available to be read
from the read end of the pipe.
/**
Emitted when there are bytes available to be read
from the read end of the pipe.
\sa bytesAvailable()
*/
void readyRead();
\sa bytesAvailable()
*/
void readyRead();
/**
Emitted when bytes have been written to the
write end of the pipe.
/**
Emitted when bytes have been written to the
write end of the pipe.
\param bytes the number of bytes written
*/
void bytesWritten(int bytes);
\param bytes the number of bytes written
*/
void bytesWritten(int bytes);
/**
Emitted when this end of the pipe is closed as a result of calling
close()
/**
Emitted when this end of the pipe is closed as a result of calling
close()
If this is the write end of the pipe and there is data still
pending to write, this signal will be emitted once all of the data
has been written.
If this is the write end of the pipe and there is data still
pending to write, this signal will be emitted once all of the data
has been written.
To be notified if the other end of the pipe has been closed, see
error().
*/
void closed();
To be notified if the other end of the pipe has been closed, see
error().
*/
void closed();
/**
Emitted when the pipe encounters an error trying to read or write,
or if the other end of the pipe has been closed
/**
Emitted when the pipe encounters an error trying to read or write,
or if the other end of the pipe has been closed
\param e the reason for error
*/
void error(QCA::QPipeEnd::Error e);
\param e the reason for error
*/
void error(QCA::QPipeEnd::Error e);
private:
Q_DISABLE_COPY(QPipeEnd)
Q_DISABLE_COPY(QPipeEnd)
class Private;
friend class Private;
Private *d;
class Private;
friend class Private;
Private *d;
};
/**
@ -480,53 +478,59 @@ private:
class QCA_EXPORT QPipe
{
public:
/**
Standard constructor
/**
Standard constructor
\note You must call create() before using the pipe ends.
\note You must call create() before using the pipe ends.
\param parent the parent object for this object
*/
QPipe(QObject *parent = 0);
\param parent the parent object for this object
*/
QPipe(QObject *parent = nullptr);
~QPipe();
~QPipe();
/**
Reset the pipe.
/**
Reset the pipe.
At this point, the readEnd() and writeEnd() calls
will no longer be valid.
*/
void reset();
At this point, the readEnd() and writeEnd() calls
will no longer be valid.
*/
void reset();
#ifdef QPIPE_SECURE
/**
Create the pipe
/**
Create the pipe
\param secure whether to use secure memory (true) or not (false)
*/
bool create(bool secure = false);
\param secure whether to use secure memory (true) or not (false)
*/
bool create(bool secure = false);
#else
/**
Create the pipe
*/
bool create();
/**
Create the pipe
*/
bool create();
#endif
/**
The read end of the pipe.
*/
QPipeEnd & readEnd() { return i; }
/**
The read end of the pipe.
*/
QPipeEnd &readEnd()
{
return i;
}
/**
The write end of the pipe.
*/
QPipeEnd & writeEnd() { return o; }
/**
The write end of the pipe.
*/
QPipeEnd &writeEnd()
{
return o;
}
private:
Q_DISABLE_COPY(QPipe)
Q_DISABLE_COPY(QPipe)
QPipeEnd i, o;
QPipeEnd i, o;
};
}

40
metainfo.yaml Normal file
View File

@ -0,0 +1,40 @@
maintainer: sitter
fancyname: QCA
description: QCA (Qt Cryptographic Architecture) provides a straightforward and cross-platform crypto API
platforms:
- name: Linux
- name: FreeBSD
- name: Windows
# - name: MacOSX
# - name: Android
release: true
public_lib: true
public_source_dirs:
- include/QtCrypto
- examples
public_doc_dir:
- docs
public_example_dirs:
- examples/aes-cmac
- examples/base64test
- examples/certtest
- examples/ciphertest
- examples/cms
- examples/cmssigner
- examples/eventhandlerdemo
- examples/hashtest
- examples/hextest
- examples/keyloader
- examples/mactest
- examples/md5crypt
- examples/providertest
- examples/publickeyexample
- examples/randomtest
- examples/rsatest
- examples/saslclient
- examples/saslserver
- examples/ssltest
- examples/sslservtest
- examples/tlssocket
irc: kde-devel
mailinglist: kde-core-devel

View File

@ -22,36 +22,36 @@ if(NOT_PLUGIN_LIST)
set(WITH_${PLUGIN}_PLUGIN "yes")
elseif("${BUILD_PLUGINS}" STREQUAL "auto")
set(WITH_${PLUGIN}_PLUGIN "auto")
else("${BUILD_PLUGINS}" STREQUAL "all")
else()
set(WITH_${PLUGIN}_PLUGIN "no")
endif("${BUILD_PLUGINS}" STREQUAL "all")
endif()
elseif(NOT WITH_${PLUGIN}_PLUGIN)
set(WITH_${PLUGIN}_PLUGIN "no")
elseif("${WITH_${PLUGIN}_PLUGIN}" STREQUAL "auto")
set(WITH_${PLUGIN}_PLUGIN "auto")
else("${WITH_${PLUGIN}_PLUGIN}" STREQUAL "")
else()
set(WITH_${PLUGIN}_PLUGIN "yes")
endif("${WITH_${PLUGIN}_PLUGIN}" STREQUAL "")
endif()
# Build plugin if yes or auto
if(WITH_${PLUGIN}_PLUGIN)
add_subdirectory("qca-${PLUGIN}")
else(WITH_${PLUGIN}_PLUGIN)
else()
disable_plugin(${PLUGIN})
endif(WITH_${PLUGIN}_PLUGIN)
endif()
endforeach(PLUGIN IN LISTS PLUGINS)
else(NOT_PLUGIN_LIST)
else()
# BUILD_PLUGINS has list plugins to builds
foreach(PLUGIN IN LISTS PLUGINS)
list(FIND BUILD_PLUGINS "${PLUGIN}" PLUGIN_INDEX)
if(PLUGIN_INDEX GREATER -1)
set(WITH_${PLUGIN}_PLUGIN "yes")
add_subdirectory("qca-${PLUGIN}")
else(PLUGIN_INDEX GREATER -1)
else()
disable_plugin(${PLUGIN})
endif(PLUGIN_INDEX GREATER -1)
endif()
endforeach(PLUGIN IN LISTS PLUGINS)
endif(NOT_PLUGIN_LIST)
endif()
message("")
message("Plugins:")

View File

@ -1,22 +1,25 @@
find_package(PkgConfig REQUIRED)
if(WITH_botan_PLUGIN STREQUAL "yes")
find_package(Botan REQUIRED)
else(WITH_botan_PLUGIN STREQUAL "yes")
find_package(Botan)
endif(WITH_botan_PLUGIN STREQUAL "yes")
pkg_check_modules(BOTAN REQUIRED IMPORTED_TARGET botan-2)
else()
pkg_check_modules(BOTAN IMPORTED_TARGET botan-2)
endif()
if(BOTAN_FOUND)
enable_plugin("botan")
set(QCA_BOTAN_SOURCES qca-botan.cpp)
add_definitions(${BOTAN_CFLAGS})
my_automoc(QCA_BOTAN_SOURCES)
add_library(qca-botan ${PLUGIN_TYPE} ${QCA_BOTAN_SOURCES})
if(APPLE AND ${PLUGIN_TYPE} STREQUAL "MODULE")
set_property(TARGET qca-botan PROPERTY SUFFIX ".dylib")
endif()
target_link_libraries(qca-botan ${QT_QTCORE_LIBRARY} ${QCA_LIB_NAME} ${BOTAN_LIBRARIES})
if(QT6)
target_link_libraries(qca-botan Qt6::Core ${QCA_LIB_NAME} PkgConfig::BOTAN)
else()
target_link_libraries(qca-botan Qt5::Core ${QCA_LIB_NAME} PkgConfig::BOTAN)
endif()
if(NOT DEVELOPER_MODE)
install(TARGETS qca-botan
@ -27,6 +30,6 @@ if(BOTAN_FOUND)
install_pdb(qca-botan ${QCA_CRYPTO_INSTALL_DIR})
endif()
else(BOTAN_FOUND)
else()
disable_plugin("botan")
endif(BOTAN_FOUND)
endif()

File diff suppressed because it is too large Load Diff

View File

@ -1,22 +1,25 @@
if(WITH_cyrus-sasl_PLUGIN STREQUAL "yes")
find_package(Sasl2 REQUIRED)
else(WITH_cyrus-sasl_PLUGIN STREQUAL "yes")
else()
find_package(Sasl2)
endif(WITH_cyrus-sasl_PLUGIN STREQUAL "yes")
endif()
if(SASL2_FOUND)
enable_plugin("cyrus-sasl")
set(QCA_SASL_SOURCES qca-cyrus-sasl.cpp)
include_directories( ${SASL2_INCLUDE_DIR} )
my_automoc( QCA_SASL_SOURCES )
add_library(qca-cyrus-sasl ${PLUGIN_TYPE} ${QCA_SASL_SOURCES})
if(APPLE AND ${PLUGIN_TYPE} STREQUAL "MODULE")
set_property(TARGET qca-cyrus-sasl PROPERTY SUFFIX ".dylib")
endif()
target_link_libraries(qca-cyrus-sasl ${QT_QTCORE_LIBRARY} ${QCA_LIB_NAME} ${SASL2_LIBRARIES})
if(QT6)
target_link_libraries(qca-cyrus-sasl Qt6::Core ${QCA_LIB_NAME} ${SASL2_LIBRARIES})
else()
target_link_libraries(qca-cyrus-sasl Qt5::Core ${QCA_LIB_NAME} ${SASL2_LIBRARIES})
endif()
if(NOT DEVELOPER_MODE)
install(TARGETS qca-cyrus-sasl
@ -26,6 +29,6 @@ if(SASL2_FOUND)
install_pdb(qca-cyrus-sasl ${QCA_CRYPTO_INSTALL_DIR})
endif()
else(SASL2_FOUND)
else()
disable_plugin("cyrus-sasl")
endif(SASL2_FOUND)
endif()

File diff suppressed because it is too large Load Diff

View File

@ -1,8 +1,8 @@
if(WITH_gcrypt_PLUGIN STREQUAL "yes")
find_package(LibGcrypt REQUIRED)
else(WITH_gcrypt_PLUGIN STREQUAL "yes")
else()
find_package(LibGcrypt)
endif(WITH_gcrypt_PLUGIN STREQUAL "yes")
endif()
if(LIBGCRYPT_FOUND)
include(CheckTypeSize)
@ -19,14 +19,17 @@ if(LIBGCRYPT_FOUND)
set(QCA_GCRYPT_SOURCES qca-gcrypt.cpp)
add_definitions(${LIBGCRYPT_CFLAGS})
my_automoc(QCA_GCRYPT_SOURCES)
add_library(qca-gcrypt ${PLUGIN_TYPE} ${QCA_GCRYPT_SOURCES})
if(APPLE AND ${PLUGIN_TYPE} STREQUAL "MODULE")
set_property(TARGET qca-gcrypt PROPERTY SUFFIX ".dylib")
endif()
target_link_libraries(qca-gcrypt ${QT_QTCORE_LIBRARY} ${QCA_LIB_NAME} ${LIBGCRYPT_LIBRARIES})
if(QT6)
target_link_libraries(qca-gcrypt Qt6::Core ${QCA_LIB_NAME} ${LIBGCRYPT_LIBRARIES})
else()
target_link_libraries(qca-gcrypt Qt5::Core ${QCA_LIB_NAME} ${LIBGCRYPT_LIBRARIES})
endif()
if(NOT DEVELOPER_MODE)
install(TARGETS qca-gcrypt
@ -36,10 +39,10 @@ if(LIBGCRYPT_FOUND)
install_pdb(qca-gcrypt ${QCA_CRYPTO_INSTALL_DIR})
endif()
else(HAVE_GCRY_ERROR_T)
else()
message(STATUS "libgcrypt seems to be too old")
disable_plugin("gcrypt")
endif(HAVE_GCRY_ERROR_T)
else(LIBGCRYPT_FOUND)
endif()
else()
disable_plugin("gcrypt")
endif(LIBGCRYPT_FOUND)
endif()

120
plugins/qca-gcrypt/hkdf.c Normal file
View File

@ -0,0 +1,120 @@
/*
* Copyright (C) 2011 Collabora Ltd.
* Copyright (C) 2018 Alexander Volkov <a.volkov@rusbitech.ru>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This program 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*
* Author: Stef Walter <stefw@collabora.co.uk>
*/
#include <gcrypt.h>
static gcry_error_t gcry_hkdf(int algo,
const char *input,
size_t n_input,
const char *salt,
size_t n_salt,
const char *info,
size_t n_info,
char * output,
size_t n_output)
{
void * alloc = nullptr;
void * buffer = nullptr;
gcry_md_hd_t md1, md2;
unsigned int hash_len;
int i;
size_t step, n_buffer;
char * at;
gcry_error_t gcry;
hash_len = gcry_md_get_algo_dlen(algo);
if (hash_len == 0) {
return GPG_ERR_UNSUPPORTED_ALGORITHM;
}
if (n_output > 255 * hash_len) {
return GPG_ERR_TOO_LARGE;
}
/* Buffer we need to for intermediate stuff */
buffer = gcry_malloc_secure(hash_len);
if (!buffer) {
return GPG_ERR_ENOMEM;
}
n_buffer = 0;
/* Salt defaults to hash_len zeros */
if (!salt) {
alloc = gcry_calloc_secure(hash_len, 1);
if (!alloc) {
return GPG_ERR_ENOMEM;
}
salt = (const char *)alloc;
n_salt = hash_len;
}
/* Step 1: Extract */
gcry = gcry_md_open(&md1, algo, GCRY_MD_FLAG_HMAC | GCRY_MD_FLAG_SECURE);
if (gcry != GPG_ERR_NO_ERROR) {
goto done;
}
gcry = gcry_md_setkey(md1, salt, n_salt);
if (gcry != GPG_ERR_NO_ERROR) {
gcry_md_close(md1);
goto done;
}
gcry_md_write(md1, input, n_input);
/* Step 2: Expand */
gcry = gcry_md_open(&md2, algo, GCRY_MD_FLAG_HMAC | GCRY_MD_FLAG_SECURE);
if (gcry != GPG_ERR_NO_ERROR) {
gcry_md_close(md1);
goto done;
}
gcry = gcry_md_setkey(md2, gcry_md_read(md1, algo), hash_len);
if (gcry != GPG_ERR_NO_ERROR) {
gcry_md_close(md2);
gcry_md_close(md1);
goto done;
}
gcry_md_close(md1);
at = output;
for (i = 1; i < 256; ++i) {
gcry_md_reset(md2);
gcry_md_write(md2, buffer, n_buffer);
gcry_md_write(md2, info, n_info);
gcry_md_putc(md2, i);
n_buffer = hash_len;
memcpy(buffer, gcry_md_read(md2, algo), n_buffer);
step = n_buffer < n_output ? n_buffer : n_output;
memcpy(at, buffer, step);
n_output -= step;
at += step;
if (!n_output)
break;
}
gcry_md_close(md2);
done:
gcry_free(alloc);
gcry_free(buffer);
return gcry;
}

View File

@ -45,153 +45,151 @@
* Output: DK derived key, a dkLen-octet string
*/
gcry_error_t
gcry_pbkdf2 (int PRF, const char *P, size_t Plen, const char *S,
size_t Slen, unsigned int c, unsigned int dkLen, char *DK)
static gcry_error_t gcry_pbkdf2(int PRF,
const char * P,
size_t Plen,
const char * S,
size_t Slen,
unsigned int c,
unsigned int dkLen,
char * DK)
{
gcry_md_hd_t prf;
gcry_error_t rc;
char *U;
unsigned int u;
unsigned int hLen;
unsigned int l;
unsigned int r;
unsigned char *p;
unsigned int i;
unsigned int k;
gcry_md_hd_t prf;
gcry_error_t rc;
char * U;
unsigned int u;
unsigned int hLen;
unsigned int l;
unsigned int r;
unsigned char *p;
unsigned int i;
unsigned int k;
hLen = gcry_md_get_algo_dlen (PRF);
if (hLen == 0)
return GPG_ERR_UNSUPPORTED_ALGORITHM;
hLen = gcry_md_get_algo_dlen(PRF);
if (hLen == 0)
return GPG_ERR_UNSUPPORTED_ALGORITHM;
if (c == 0)
return GPG_ERR_INV_ARG;
if (c == 0)
return GPG_ERR_INV_ARG;
if (dkLen == 0)
return GPG_ERR_TOO_SHORT;
if (dkLen == 0)
return GPG_ERR_TOO_SHORT;
/*
*
* Steps:
*
* 1. If dkLen > (2^32 - 1) * hLen, output "derived key too long" and
* stop.
*/
/*
*
* Steps:
*
* 1. If dkLen > (2^32 - 1) * hLen, output "derived key too long" and
* stop.
*/
if (dkLen > 4294967295U)
return GPG_ERR_TOO_LARGE;
if (dkLen > 4294967295U)
return GPG_ERR_TOO_LARGE;
/*
* 2. Let l be the number of hLen-octet blocks in the derived key,
* rounding up, and let r be the number of octets in the last
* block:
*
* l = CEIL (dkLen / hLen) ,
* r = dkLen - (l - 1) * hLen .
*
* Here, CEIL (x) is the "ceiling" function, i.e. the smallest
* integer greater than, or equal to, x.
*/
/*
* 2. Let l be the number of hLen-octet blocks in the derived key,
* rounding up, and let r be the number of octets in the last
* block:
*
* l = CEIL (dkLen / hLen) ,
* r = dkLen - (l - 1) * hLen .
*
* Here, CEIL (x) is the "ceiling" function, i.e. the smallest
* integer greater than, or equal to, x.
*/
l = dkLen / hLen;
if (dkLen % hLen)
l++;
r = dkLen - (l - 1) * hLen;
l = dkLen / hLen;
if (dkLen % hLen)
l++;
r = dkLen - (l - 1) * hLen;
/*
* 3. For each block of the derived key apply the function F defined
* below to the password P, the salt S, the iteration count c, and
* the block index to compute the block:
*
* T_1 = F (P, S, c, 1) ,
* T_2 = F (P, S, c, 2) ,
* ...
* T_l = F (P, S, c, l) ,
*
* where the function F is defined as the exclusive-or sum of the
* first c iterates of the underlying pseudorandom function PRF
* applied to the password P and the concatenation of the salt S
* and the block index i:
*
* F (P, S, c, i) = U_1 \xor U_2 \xor ... \xor U_c
*
* where
*
* U_1 = PRF (P, S || INT (i)) ,
* U_2 = PRF (P, U_1) ,
* ...
* U_c = PRF (P, U_{c-1}) .
*
* Here, INT (i) is a four-octet encoding of the integer i, most
* significant octet first.
*
* 4. Concatenate the blocks and extract the first dkLen octets to
* produce a derived key DK:
*
* DK = T_1 || T_2 || ... || T_l<0..r-1>
*
* 5. Output the derived key DK.
*
* Note. The construction of the function F follows a "belt-and-
* suspenders" approach. The iterates U_i are computed recursively to
* remove a degree of parallelism from an opponent; they are exclusive-
* ored together to reduce concerns about the recursion degenerating
* into a small set of values.
*
*/
rc = gcry_md_open (&prf, PRF, GCRY_MD_FLAG_HMAC | GCRY_MD_FLAG_SECURE);
if (rc != GPG_ERR_NO_ERROR)
/*
* 3. For each block of the derived key apply the function F defined
* below to the password P, the salt S, the iteration count c, and
* the block index to compute the block:
*
* T_1 = F (P, S, c, 1) ,
* T_2 = F (P, S, c, 2) ,
* ...
* T_l = F (P, S, c, l) ,
*
* where the function F is defined as the exclusive-or sum of the
* first c iterates of the underlying pseudorandom function PRF
* applied to the password P and the concatenation of the salt S
* and the block index i:
*
* F (P, S, c, i) = U_1 \xor U_2 \xor ... \xor U_c
*
* where
*
* U_1 = PRF (P, S || INT (i)) ,
* U_2 = PRF (P, U_1) ,
* ...
* U_c = PRF (P, U_{c-1}) .
*
* Here, INT (i) is a four-octet encoding of the integer i, most
* significant octet first.
*
* 4. Concatenate the blocks and extract the first dkLen octets to
* produce a derived key DK:
*
* DK = T_1 || T_2 || ... || T_l<0..r-1>
*
* 5. Output the derived key DK.
*
* Note. The construction of the function F follows a "belt-and-
* suspenders" approach. The iterates U_i are computed recursively to
* remove a degree of parallelism from an opponent; they are exclusive-
* ored together to reduce concerns about the recursion degenerating
* into a small set of values.
*
*/
rc = gcry_md_open(&prf, PRF, GCRY_MD_FLAG_HMAC | GCRY_MD_FLAG_SECURE);
if (rc != GPG_ERR_NO_ERROR)
return rc;
U = (char *)gcry_malloc(hLen);
if (!U) {
rc = GPG_ERR_ENOMEM;
goto done;
}
for (i = 1; i <= l; i++) {
memset(DK + (i - 1) * hLen, 0, i == l ? r : hLen);
for (u = 1; u <= c; u++) {
gcry_md_reset(prf);
rc = gcry_md_setkey(prf, P, Plen);
if (rc != GPG_ERR_NO_ERROR) {
goto done;
}
if (u == 1) {
char tmp[4];
gcry_md_write(prf, S, Slen);
tmp[0] = (i & 0xff000000) >> 24;
tmp[1] = (i & 0x00ff0000) >> 16;
tmp[2] = (i & 0x0000ff00) >> 8;
tmp[3] = (i & 0x000000ff) >> 0;
gcry_md_write(prf, tmp, 4);
} else
gcry_md_write(prf, U, hLen);
p = gcry_md_read(prf, PRF);
if (p == nullptr) {
rc = GPG_ERR_CONFIGURATION;
goto done;
}
memcpy(U, p, hLen);
for (k = 0; k < (i == l ? r : hLen); k++)
DK[(i - 1) * hLen + k] ^= U[k];
}
}
rc = GPG_ERR_NO_ERROR;
done:
gcry_md_close(prf);
gcry_free(U);
return rc;
U = (char*)gcry_malloc(hLen);
if (!U)
{
rc = GPG_ERR_ENOMEM;
goto done;
}
for (i = 1; i <= l; i++)
{
memset(DK + (i - 1) * hLen, 0, i == l ? r : hLen);
for (u = 1; u <= c; u++)
{
gcry_md_reset (prf);
rc = gcry_md_setkey (prf, P, Plen);
if (rc != GPG_ERR_NO_ERROR) {
goto done;
}
if (u == 1)
{
char tmp[4];
gcry_md_write (prf, S, Slen);
tmp[0] = (i & 0xff000000) >> 24;
tmp[1] = (i & 0x00ff0000) >> 16;
tmp[2] = (i & 0x0000ff00) >> 8;
tmp[3] = (i & 0x000000ff) >> 0;
gcry_md_write (prf, tmp, 4);
}
else
gcry_md_write (prf, U, hLen);
p = gcry_md_read (prf, PRF);
if (p == NULL)
{
rc = GPG_ERR_CONFIGURATION;
goto done;
}
memcpy (U, p, hLen);
for (k = 0; k < (i == l ? r : hLen); k++)
DK[(i - 1) * hLen + k] ^= U[k];
}
}
rc = GPG_ERR_NO_ERROR;
done:
gcry_md_close (prf);
gcry_free(U);
return rc;
}

File diff suppressed because it is too large Load Diff

View File

@ -2,11 +2,8 @@
enable_plugin("gnupg")
set(QCA_GNUPG_MOC_SOURCES
set(QCA_GNUPG_SOURCES
qca-gnupg.cpp
)
set(QCA_GNUPG_NONMOC_SOURCES
gpgop.cpp
utils.cpp
gpgproc/sprocess.cpp
@ -21,30 +18,39 @@ set(QCA_GNUPG_NONMOC_SOURCES
gpgproc/gpgproc.cpp
)
my_automoc(QCA_GNUPG_MOC_SOURCES)
set(QCA_GNUPG_HEADERS
gpgaction.h
ringwatch.h
gpgop.h
gpgop_p.h
lineconverter.h
mypgpkeycontext.h
mykeystoreentry.h
mykeystorelist.h
gpgproc/gpgproc_p.h
gpgproc/sprocess.h
gpgproc/gpgproc.h
utils.h
mymessagecontext.h
myopenpgpcontext.h
)
qt4_wrap_cpp(EXTRA_GNUPG_SOURCES gpgop.h)
qt4_wrap_cpp(EXTRA_GNUPG_SOURCES gpgop_p.h)
qt4_wrap_cpp(EXTRA_GNUPG_SOURCES gpgproc/gpgproc.h)
qt4_wrap_cpp(EXTRA_GNUPG_SOURCES gpgproc/gpgproc_p.h)
qt4_wrap_cpp(EXTRA_GNUPG_SOURCES gpgproc/sprocess.h)
qt4_wrap_cpp(EXTRA_GNUPG_SOURCES ringwatch.h)
qt4_wrap_cpp(EXTRA_GNUPG_SOURCES mykeystorelist.h)
qt4_wrap_cpp(EXTRA_GNUPG_SOURCES mymessagecontext.h)
qt4_wrap_cpp(EXTRA_GNUPG_SOURCES gpgaction.h)
add_library(qca-gnupg ${PLUGIN_TYPE} ${QCA_GNUPG_MOC_SOURCES} ${QCA_GNUPG_NONMOC_SOURCES} ${EXTRA_GNUPG_SOURCES})
add_library(qca-gnupg ${PLUGIN_TYPE} ${QCA_GNUPG_SOURCES} ${EXTRA_GNUPG_SOURCES} ${QCA_GNUPG_HEADERS})
if(APPLE AND ${PLUGIN_TYPE} STREQUAL "MODULE")
set_property(TARGET qca-gnupg PROPERTY SUFFIX ".dylib")
endif()
include_directories(gpgproc)
target_link_libraries(qca-gnupg ${QT_QTCORE_LIBRARY} ${QCA_LIB_NAME})
if(QT6)
target_link_libraries(qca-gnupg Qt6::Core ${QCA_LIB_NAME})
else()
target_link_libraries(qca-gnupg Qt5::Core ${QCA_LIB_NAME})
endif()
if (WIN32)
target_link_libraries(qca-gnupg advapi32)
endif (WIN32)
endif()
if(NOT DEVELOPER_MODE)
install(TARGETS qca-gnupg DESTINATION

File diff suppressed because it is too large Load Diff

View File

@ -19,13 +19,13 @@
#pragma once
#include "lineconverter.h"
#include "qca_safetimer.h"
#include "gpgop.h"
#include "gpgproc.h"
#include "lineconverter.h"
#include "qca_safetimer.h"
#include <QByteArray>
#include <QObject>
#include <QStringList>
#include <QByteArray>
#ifdef GPG_PROFILE
#include <QTime>
@ -35,107 +35,118 @@ namespace gpgQCAPlugin {
class GpgAction : public QObject
{
Q_OBJECT
Q_OBJECT
public:
struct Input
{
QString bin;
GpgOp::Type op;
bool opt_ascii, opt_noagent, opt_alwaystrust;
QString opt_pubfile, opt_secfile;
QStringList recip_ids;
QString signer_id;
QByteArray sig;
QByteArray inkey;
QString export_key_id;
QString delete_key_fingerprint;
struct Input
{
QString bin;
GpgOp::Type op;
bool opt_ascii, opt_noagent, opt_alwaystrust;
QString opt_pubfile, opt_secfile;
QStringList recip_ids;
QString signer_id;
QByteArray sig;
QByteArray inkey;
QString export_key_id;
QString delete_key_fingerprint;
Input() : opt_ascii(false), opt_noagent(false), opt_alwaystrust(false) {}
};
Input()
: opt_ascii(false)
, opt_noagent(false)
, opt_alwaystrust(false)
{
}
};
struct Output
{
bool success;
GpgOp::Error errorCode;
GpgOp::KeyList keys;
QString keyringFile;
QString encryptedToId;
bool wasSigned;
QString signerId;
QDateTime timestamp;
GpgOp::VerifyResult verifyResult;
struct Output
{
bool success;
GpgOp::Error errorCode;
GpgOp::KeyList keys;
QString keyringFile;
QString encryptedToId;
bool wasSigned;
QString signerId;
QDateTime timestamp;
GpgOp::VerifyResult verifyResult;
QString homeDir;
Output() : success(false), errorCode(GpgOp::ErrorUnknown), wasSigned(false) {}
};
Output()
: success(false)
, errorCode(GpgOp::ErrorUnknown)
, wasSigned(false)
{
}
};
Input input;
Output output;
Input input;
Output output;
GpgAction(QObject *parent = 0);
~GpgAction();
void reset();
void start();
GpgAction(QObject *parent = nullptr);
~GpgAction() override;
void reset();
void start();
#ifdef QPIPE_SECURE
void submitPassphrase(const QCA::SecureArray &a);
void submitPassphrase(const QCA::SecureArray &a);
#else
void submitPassphrase(const QByteArray &a);
void submitPassphrase(const QByteArray &a);
#endif
public slots:
QByteArray read();
void write(const QByteArray &in);
void endWrite();
void cardOkay();
QString readDiagnosticText();
public Q_SLOTS:
QByteArray read();
void write(const QByteArray &in);
void endWrite();
void cardOkay();
QString readDiagnosticText();
signals:
void readyRead();
void bytesWritten(int bytes);
void finished();
void needPassphrase(const QString &keyId);
void needCard();
void readyReadDiagnosticText();
Q_SIGNALS:
void readyRead();
void bytesWritten(int bytes);
void finished();
void needPassphrase(const QString &keyId);
void needCard();
void readyReadDiagnosticText();
private:
void submitCommand(const QByteArray &a);
void submitCommand(const QByteArray &a);
// since str is taken as a value, it is ok to use the same variable for 'rest'
QString nextArg(QString str, QString *rest = 0);
void processStatusLine(const QString &line);
void processResult(int code);
void ensureDTextEmit();
// since str is taken as a value, it is ok to use the same variable for 'rest'
QString nextArg(QString str, QString *rest = nullptr);
void processStatusLine(const QString &line);
void processResult(int code);
void ensureDTextEmit();
GPGProc proc;
bool collectOutput, allowInput;
LineConverter readConv, writeConv;
bool readText, writeText;
QByteArray buf_stdout, buf_stderr;
bool useAux;
QString passphraseKeyId;
bool signing, decryptGood, signGood;
GpgOp::Error curError;
bool badPassphrase;
bool need_submitPassphrase, need_cardOkay;
QString diagnosticText;
QCA::SafeTimer dtextTimer;
GPGProc proc;
bool collectOutput, allowInput;
LineConverter readConv, writeConv;
bool readText, writeText;
QByteArray buf_stdout, buf_stderr;
bool useAux;
QString passphraseKeyId;
bool signing, decryptGood, signGood;
GpgOp::Error curError;
bool badPassphrase;
bool need_submitPassphrase, need_cardOkay;
QString diagnosticText;
QCA::SafeTimer dtextTimer;
bool utf8Output;
#ifdef GPG_PROFILE
QTime timer;
QTime timer;
#endif
private slots:
void t_dtext();
void proc_error(gpgQCAPlugin::GPGProc::Error e);
void proc_finished(int exitCode);
void proc_readyReadStdout();
void proc_readyReadStderr();
void proc_readyReadStatusLines();
void proc_bytesWrittenStdin(int bytes);
void proc_bytesWrittenAux(int bytes);
void proc_bytesWrittenCommand(int);
void proc_debug(const QString &str);
void appendDiagnosticText(const QString &line);
private Q_SLOTS:
void t_dtext();
void proc_error(gpgQCAPlugin::GPGProc::Error e);
void proc_finished(int exitCode);
void proc_readyReadStdout();
void proc_readyReadStderr();
void proc_readyReadStatusLines();
void proc_bytesWrittenStdin(int bytes);
void proc_bytesWrittenAux(int bytes);
void proc_bytesWrittenCommand(int);
void proc_debug(const QString &str);
void appendDiagnosticText(const QString &line);
};
} // end namespace gpgQCAPlugin

View File

@ -17,9 +17,9 @@
*
*/
#include "gpgop_p.h"
#include "gpgop.h"
#include "gpgaction.h"
#include "gpgop_p.h"
namespace gpgQCAPlugin {
@ -27,351 +27,347 @@ namespace gpgQCAPlugin {
// GpgOp
//----------------------------------------------------------------------------
GpgOp::Private::Private(GpgOp *_q)
: QObject(_q)
, sync(_q)
, q(_q)
, act(0)
, waiting(false)
: QObject(_q)
, sync(_q)
, q(_q)
, act(nullptr)
, waiting(false)
{
reset(ResetAll);
reset(ResetAll);
}
GpgOp::Private::~Private()
{
reset(ResetAll);
reset(ResetAll);
}
void GpgOp::Private::reset(ResetMode mode)
{
if(act)
{
act->disconnect(this);
act->setParent(0);
act->deleteLater();
if (act) {
act->disconnect(this);
act->setParent(nullptr);
act->deleteLater();
act = 0;
}
act = nullptr;
}
if(mode >= ResetSessionAndData)
{
output = GpgAction::Output();
result.clear();
diagnosticText = QString();
eventList.clear();
}
if (mode >= ResetSessionAndData) {
output = GpgAction::Output();
result.clear();
diagnosticText = QString();
eventList.clear();
}
if(mode >= ResetAll)
{
opt_ascii = false;
opt_noagent = false;
opt_alwaystrust = false;
opt_pubfile = QString();
opt_secfile = QString();
}
if (mode >= ResetAll) {
opt_ascii = false;
opt_noagent = false;
opt_alwaystrust = false;
opt_pubfile = QString();
opt_secfile = QString();
}
}
void GpgOp::Private::make_act(GpgOp::Type _op)
{
reset(ResetSessionAndData);
reset(ResetSessionAndData);
op = _op;
op = _op;
act = new GpgAction(this);
act = new GpgAction(this);
connect(act, SIGNAL(readyRead()), SLOT(act_readyRead()));
connect(act, SIGNAL(bytesWritten(int)), SLOT(act_bytesWritten(int)));
connect(act, SIGNAL(needPassphrase(const QString &)), SLOT(act_needPassphrase(const QString &)));
connect(act, SIGNAL(needCard()), SLOT(act_needCard()));
connect(act, SIGNAL(finished()), SLOT(act_finished()));
connect(act, SIGNAL(readyReadDiagnosticText()), SLOT(act_readyReadDiagnosticText()));
connect(act, &GpgAction::readyRead, this, &GpgOp::Private::act_readyRead);
connect(act, &GpgAction::bytesWritten, this, &GpgOp::Private::act_bytesWritten);
connect(act, &GpgAction::needPassphrase, this, &GpgOp::Private::act_needPassphrase);
connect(act, &GpgAction::needCard, this, &GpgOp::Private::act_needCard);
connect(act, &GpgAction::finished, this, &GpgOp::Private::act_finished);
connect(act, &GpgAction::readyReadDiagnosticText, this, &GpgOp::Private::act_readyReadDiagnosticText);
act->input.bin = bin;
act->input.op = op;
act->input.opt_ascii = opt_ascii;
act->input.opt_noagent = opt_noagent;
act->input.opt_alwaystrust = opt_alwaystrust;
act->input.opt_pubfile = opt_pubfile;
act->input.opt_secfile = opt_secfile;
act->input.bin = bin;
act->input.op = op;
act->input.opt_ascii = opt_ascii;
act->input.opt_noagent = opt_noagent;
act->input.opt_alwaystrust = opt_alwaystrust;
act->input.opt_pubfile = opt_pubfile;
act->input.opt_secfile = opt_secfile;
}
void GpgOp::Private::eventReady(const GpgOp::Event &e)
{
eventList += e;
sync.conditionMet();
eventList += e;
sync.conditionMet();
}
void GpgOp::Private::eventReady(GpgOp::Event::Type type)
{
GpgOp::Event e;
e.type = type;
eventReady(e);
GpgOp::Event e;
e.type = type;
eventReady(e);
}
void GpgOp::Private::eventReady(GpgOp::Event::Type type, int written)
{
GpgOp::Event e;
e.type = type;
e.written = written;
eventReady(e);
GpgOp::Event e;
e.type = type;
e.written = written;
eventReady(e);
}
void GpgOp::Private::eventReady(GpgOp::Event::Type type, const QString &keyId)
{
GpgOp::Event e;
e.type = type;
e.keyId = keyId;
eventReady(e);
GpgOp::Event e;
e.type = type;
e.keyId = keyId;
eventReady(e);
}
void GpgOp::Private::act_readyRead()
{
if(waiting)
eventReady(GpgOp::Event::ReadyRead);
else
emit q->readyRead();
if (waiting)
eventReady(GpgOp::Event::ReadyRead);
else
emit q->readyRead();
}
void GpgOp::Private::act_bytesWritten(int bytes)
{
if(waiting)
eventReady(GpgOp::Event::BytesWritten, bytes);
else
emit q->bytesWritten(bytes);
if (waiting)
eventReady(GpgOp::Event::BytesWritten, bytes);
else
emit q->bytesWritten(bytes);
}
void GpgOp::Private::act_needPassphrase(const QString &keyId)
{
if(waiting)
eventReady(GpgOp::Event::NeedPassphrase, keyId);
else
emit q->needPassphrase(keyId);
if (waiting)
eventReady(GpgOp::Event::NeedPassphrase, keyId);
else
emit q->needPassphrase(keyId);
}
void GpgOp::Private::act_needCard()
{
if(waiting)
eventReady(GpgOp::Event::NeedCard);
else
emit q->needCard();
if (waiting)
eventReady(GpgOp::Event::NeedCard);
else
emit q->needCard();
}
void GpgOp::Private::act_readyReadDiagnosticText()
{
QString s = act->readDiagnosticText();
//printf("dtext ready: [%s]\n", qPrintable(s));
diagnosticText += s;
const QString s = act->readDiagnosticText();
// printf("dtext ready: [%s]\n", qPrintable(s));
diagnosticText += s;
if(waiting)
eventReady(GpgOp::Event::ReadyReadDiagnosticText);
else
emit q->readyReadDiagnosticText();
if (waiting)
eventReady(GpgOp::Event::ReadyReadDiagnosticText);
else
emit q->readyReadDiagnosticText();
}
void GpgOp::Private::act_finished()
{
#ifdef GPG_PROFILE
if(op == GpgOp::Encrypt)
printf("<< doEncrypt: %d >>\n", timer.elapsed());
if (op == GpgOp::Encrypt)
printf("<< doEncrypt: %d >>\n", timer.elapsed());
#endif
result = act->read();
diagnosticText += act->readDiagnosticText();
output = act->output;
result = act->read();
diagnosticText += act->readDiagnosticText();
output = act->output;
QMap<int, QString> errmap;
errmap[GpgOp::ErrorProcess] = "ErrorProcess";
errmap[GpgOp::ErrorPassphrase] = "ErrorPassphrase";
errmap[GpgOp::ErrorFormat] = "ErrorFormat";
errmap[GpgOp::ErrorSignerExpired] = "ErrorSignerExpired";
errmap[GpgOp::ErrorEncryptExpired] = "ErrorEncryptExpired";
errmap[GpgOp::ErrorEncryptUntrusted] = "ErrorEncryptUntrusted";
errmap[GpgOp::ErrorEncryptInvalid] = "ErrorEncryptInvalid";
errmap[GpgOp::ErrorDecryptNoKey] = "ErrorDecryptNoKey";
errmap[GpgOp::ErrorUnknown] = "ErrorUnknown";
if(output.success)
diagnosticText += "GpgAction success\n";
else
diagnosticText += QString("GpgAction error: %1\n").arg(errmap[output.errorCode]);
QMap<int, QString> errmap;
errmap[GpgOp::ErrorProcess] = QStringLiteral("ErrorProcess");
errmap[GpgOp::ErrorPassphrase] = QStringLiteral("ErrorPassphrase");
errmap[GpgOp::ErrorFormat] = QStringLiteral("ErrorFormat");
errmap[GpgOp::ErrorSignerExpired] = QStringLiteral("ErrorSignerExpired");
errmap[GpgOp::ErrorEncryptExpired] = QStringLiteral("ErrorEncryptExpired");
errmap[GpgOp::ErrorEncryptUntrusted] = QStringLiteral("ErrorEncryptUntrusted");
errmap[GpgOp::ErrorEncryptInvalid] = QStringLiteral("ErrorEncryptInvalid");
errmap[GpgOp::ErrorDecryptNoKey] = QStringLiteral("ErrorDecryptNoKey");
errmap[GpgOp::ErrorUnknown] = QStringLiteral("ErrorUnknown");
if (output.success)
diagnosticText += QStringLiteral("GpgAction success\n");
else
diagnosticText += QStringLiteral("GpgAction error: %1\n").arg(errmap[output.errorCode]);
if(output.wasSigned)
{
QString s;
if(output.verifyResult == GpgOp::VerifyGood)
s = "VerifyGood";
else if(output.verifyResult == GpgOp::VerifyBad)
s = "VerifyBad";
else
s = "VerifyNoKey";
diagnosticText += QString("wasSigned: verifyResult: %1\n").arg(s);
}
if (output.wasSigned) {
QString s;
if (output.verifyResult == GpgOp::VerifyGood)
s = QStringLiteral("VerifyGood");
else if (output.verifyResult == GpgOp::VerifyBad)
s = QStringLiteral("VerifyBad");
else
s = QStringLiteral("VerifyNoKey");
diagnosticText += QStringLiteral("wasSigned: verifyResult: %1\n").arg(s);
}
//printf("diagnosticText:\n%s", qPrintable(diagnosticText));
// printf("diagnosticText:\n%s", qPrintable(diagnosticText));
reset(ResetSession);
reset(ResetSession);
if(waiting)
eventReady(GpgOp::Event::Finished);
else
emit q->finished();
if (waiting)
eventReady(GpgOp::Event::Finished);
else
emit q->finished();
}
GpgOp::GpgOp(const QString &bin, QObject *parent)
:QObject(parent)
: QObject(parent)
{
d = new Private(this);
d->bin = bin;
d = new Private(this);
d->bin = bin;
}
GpgOp::~GpgOp()
{
delete d;
delete d;
}
void GpgOp::reset()
{
d->reset(ResetAll);
d->reset(ResetAll);
}
bool GpgOp::isActive() const
{
return (d->act ? true : false);
return (d->act ? true : false);
}
GpgOp::Type GpgOp::op() const
{
return d->op;
return d->op;
}
void GpgOp::setAsciiFormat(bool b)
{
d->opt_ascii = b;
d->opt_ascii = b;
}
void GpgOp::setDisableAgent(bool b)
{
d->opt_noagent = b;
d->opt_noagent = b;
}
void GpgOp::setAlwaysTrust(bool b)
{
d->opt_alwaystrust = b;
d->opt_alwaystrust = b;
}
void GpgOp::setKeyrings(const QString &pubfile, const QString &secfile)
{
d->opt_pubfile = pubfile;
d->opt_secfile = secfile;
d->opt_pubfile = pubfile;
d->opt_secfile = secfile;
}
void GpgOp::doCheck()
{
d->make_act(Check);
d->act->start();
d->make_act(Check);
d->act->start();
}
void GpgOp::doSecretKeyringFile()
{
d->make_act(SecretKeyringFile);
d->act->start();
d->make_act(SecretKeyringFile);
d->act->start();
}
void GpgOp::doPublicKeyringFile()
{
d->make_act(PublicKeyringFile);
d->act->start();
d->make_act(PublicKeyringFile);
d->act->start();
}
void GpgOp::doSecretKeys()
{
d->make_act(SecretKeys);
d->act->start();
d->make_act(SecretKeys);
d->act->start();
}
void GpgOp::doPublicKeys()
{
d->make_act(PublicKeys);
d->act->start();
d->make_act(PublicKeys);
d->act->start();
}
void GpgOp::doEncrypt(const QStringList &recip_ids)
{
#ifdef GPG_PROFILE
d->timer.start();
printf("<< doEncrypt >>\n");
d->timer.start();
printf("<< doEncrypt >>\n");
#endif
d->make_act(Encrypt);
d->act->input.recip_ids = recip_ids;
d->act->start();
d->make_act(Encrypt);
d->act->input.recip_ids = recip_ids;
d->act->start();
}
void GpgOp::doDecrypt()
{
d->make_act(Decrypt);
d->act->start();
d->make_act(Decrypt);
d->act->start();
}
void GpgOp::doSign(const QString &signer_id)
{
d->make_act(Sign);
d->act->input.signer_id = signer_id;
d->act->start();
d->make_act(Sign);
d->act->input.signer_id = signer_id;
d->act->start();
}
void GpgOp::doSignAndEncrypt(const QString &signer_id, const QStringList &recip_ids)
{
d->make_act(SignAndEncrypt);
d->act->input.signer_id = signer_id;
d->act->input.recip_ids = recip_ids;
d->act->start();
d->make_act(SignAndEncrypt);
d->act->input.signer_id = signer_id;
d->act->input.recip_ids = recip_ids;
d->act->start();
}
void GpgOp::doSignClearsign(const QString &signer_id)
{
d->make_act(SignClearsign);
d->act->input.signer_id = signer_id;
d->act->start();
d->make_act(SignClearsign);
d->act->input.signer_id = signer_id;
d->act->start();
}
void GpgOp::doSignDetached(const QString &signer_id)
{
d->make_act(SignDetached);
d->act->input.signer_id = signer_id;
d->act->start();
d->make_act(SignDetached);
d->act->input.signer_id = signer_id;
d->act->start();
}
void GpgOp::doVerify()
{
d->make_act(Verify);
d->act->start();
d->make_act(Verify);
d->act->start();
}
void GpgOp::doVerifyDetached(const QByteArray &sig)
{
d->make_act(VerifyDetached);
d->act->input.sig = sig;
d->act->start();
d->make_act(VerifyDetached);
d->act->input.sig = sig;
d->act->start();
}
void GpgOp::doImport(const QByteArray &in)
{
d->make_act(Import);
d->act->input.inkey = in;
d->act->start();
d->make_act(Import);
d->act->input.inkey = in;
d->act->start();
}
void GpgOp::doExport(const QString &key_id)
{
d->make_act(Export);
d->act->input.export_key_id = key_id;
d->act->start();
d->make_act(Export);
d->act->input.export_key_id = key_id;
d->act->start();
}
void GpgOp::doDeleteKey(const QString &key_fingerprint)
{
d->make_act(DeleteKey);
d->act->input.delete_key_fingerprint = key_fingerprint;
d->act->start();
d->make_act(DeleteKey);
d->act->input.delete_key_fingerprint = key_fingerprint;
d->act->start();
}
#ifdef QPIPE_SECURE
@ -380,105 +376,107 @@ void GpgOp::submitPassphrase(const QCA::SecureArray &a)
void GpgOp::submitPassphrase(const QByteArray &a)
#endif
{
d->act->submitPassphrase(a);
d->act->submitPassphrase(a);
}
void GpgOp::cardOkay()
{
d->act->cardOkay();
d->act->cardOkay();
}
QByteArray GpgOp::read()
{
if(d->act)
{
return d->act->read();
}
else
{
QByteArray a = d->result;
d->result.clear();
return a;
}
if (d->act) {
return d->act->read();
} else {
const QByteArray a = d->result;
d->result.clear();
return a;
}
}
void GpgOp::write(const QByteArray &in)
{
d->act->write(in);
d->act->write(in);
}
void GpgOp::endWrite()
{
d->act->endWrite();
d->act->endWrite();
}
QString GpgOp::readDiagnosticText()
{
QString s = d->diagnosticText;
d->diagnosticText = QString();
return s;
QString s = d->diagnosticText;
d->diagnosticText = QString();
return s;
}
GpgOp::Event GpgOp::waitForEvent(int msecs)
{
if(!d->eventList.isEmpty())
return d->eventList.takeFirst();
if (!d->eventList.isEmpty())
return d->eventList.takeFirst();
if(!d->act)
return GpgOp::Event();
if (!d->act)
return GpgOp::Event();
d->waiting = true;
d->sync.waitForCondition(msecs);
d->waiting = false;
if(!d->eventList.isEmpty())
return d->eventList.takeFirst();
else
return GpgOp::Event();
d->waiting = true;
d->sync.waitForCondition(msecs);
d->waiting = false;
if (!d->eventList.isEmpty())
return d->eventList.takeFirst();
else
return GpgOp::Event();
}
bool GpgOp::success() const
{
return d->output.success;
return d->output.success;
}
GpgOp::Error GpgOp::errorCode() const
{
return d->output.errorCode;
return d->output.errorCode;
}
GpgOp::KeyList GpgOp::keys() const
{
return d->output.keys;
return d->output.keys;
}
QString GpgOp::keyringFile() const
{
return d->output.keyringFile;
return d->output.keyringFile;
}
QString GpgOp::homeDir() const
{
return d->output.homeDir;
}
QString GpgOp::encryptedToId() const
{
return d->output.encryptedToId;
return d->output.encryptedToId;
}
bool GpgOp::wasSigned() const
{
return d->output.wasSigned;
return d->output.wasSigned;
}
QString GpgOp::signerId() const
{
return d->output.signerId;
return d->output.signerId;
}
QDateTime GpgOp::timestamp() const
{
return d->output.timestamp;
return d->output.timestamp;
}
GpgOp::VerifyResult GpgOp::verifyResult() const
{
return d->output.verifyResult;
return d->output.verifyResult;
}
}

View File

@ -20,190 +20,203 @@
#ifndef GPGOP_H
#define GPGOP_H
#include <QtCrypto>
#include "qpipe.h"
#include <QtCrypto>
namespace gpgQCAPlugin {
class GpgOp : public QObject
{
Q_OBJECT
Q_OBJECT
public:
enum Type
{
Check, // --version
SecretKeyringFile, // --list-secret-keys
PublicKeyringFile, // --list-public-keys
SecretKeys, // --fixed-list-mode --with-colons --list-secret-keys
PublicKeys, // --fixed-list-mode --with-colons --list-public-keys
Encrypt, // --encrypt
Decrypt, // --decrypt
Sign, // --sign
SignAndEncrypt, // --sign --encrypt
SignClearsign, // --clearsign
SignDetached, // --detach-sign
Verify, // --verify
VerifyDetached, // --verify
Import, // --import
Export, // --export
DeleteKey // --delete-key
};
enum Type
{
Check, // --version
SecretKeyringFile, // --list-secret-keys
PublicKeyringFile, // --list-public-keys
SecretKeys, // --fixed-list-mode --with-colons --list-secret-keys
PublicKeys, // --fixed-list-mode --with-colons --list-public-keys
Encrypt, // --encrypt
Decrypt, // --decrypt
Sign, // --sign
SignAndEncrypt, // --sign --encrypt
SignClearsign, // --clearsign
SignDetached, // --detach-sign
Verify, // --verify
VerifyDetached, // --verify
Import, // --import
Export, // --export
DeleteKey // --delete-key
};
enum VerifyResult
{
VerifyGood, // good sig
VerifyBad, // bad sig
VerifyNoKey // we don't have signer's public key
};
enum VerifyResult
{
VerifyGood, // good sig
VerifyBad, // bad sig
VerifyNoKey // we don't have signer's public key
};
enum Error
{
ErrorProcess, // startup, process, or ipc error
ErrorPassphrase, // passphrase was either wrong or not provided
ErrorFormat, // input format was bad
ErrorSignerExpired, // signing key is expired
ErrorEncryptExpired, // encrypting key is expired
ErrorEncryptUntrusted, // encrypting key is untrusted
ErrorEncryptInvalid, // encrypting key is invalid in some way
ErrorDecryptNoKey, // missing decrypt key
ErrorUnknown, // other error
ErrorSignerRevoked, // signing key is revoked
ErrorSignatureExpired, // signature is expired
ErrorEncryptRevoked // encrypting key is revoked
};
enum Error
{
ErrorProcess, // startup, process, or ipc error
ErrorPassphrase, // passphrase was either wrong or not provided
ErrorFormat, // input format was bad
ErrorSignerExpired, // signing key is expired
ErrorEncryptExpired, // encrypting key is expired
ErrorEncryptUntrusted, // encrypting key is untrusted
ErrorEncryptInvalid, // encrypting key is invalid in some way
ErrorDecryptNoKey, // missing decrypt key
ErrorUnknown, // other error
ErrorSignerRevoked, // signing key is revoked
ErrorSignatureExpired, // signature is expired
ErrorEncryptRevoked // encrypting key is revoked
};
class Event
{
public:
enum Type
{
None,
ReadyRead,
BytesWritten,
Finished,
NeedPassphrase,
NeedCard,
ReadyReadDiagnosticText
};
class Event
{
public:
enum Type
{
None,
ReadyRead,
BytesWritten,
Finished,
NeedPassphrase,
NeedCard,
ReadyReadDiagnosticText
};
Type type;
int written; // BytesWritten
QString keyId; // NeedPassphrase
Type type;
int written; // BytesWritten
QString keyId; // NeedPassphrase
Event() : type(None), written(0) {}
};
Event()
: type(None)
, written(0)
{
}
};
class KeyItem
{
public:
enum Type
{
RSA,
DSA,
ElGamal,
Unknown
};
class KeyItem
{
public:
enum Type
{
RSA,
DSA,
ElGamal,
Unknown
};
enum Caps
{
Encrypt = 0x01,
Sign = 0x02,
Certify = 0x04,
Auth = 0x08
};
enum Caps
{
Encrypt = 0x01,
Sign = 0x02,
Certify = 0x04,
Auth = 0x08
};
QString id;
Type type;
int bits;
QDateTime creationDate;
QDateTime expirationDate;
int caps; // flags OR'd together
QString fingerprint;
QString id;
Type type;
int bits;
QDateTime creationDate;
QDateTime expirationDate;
int caps; // flags OR'd together
QString fingerprint;
KeyItem() : type(Unknown), bits(0), caps(0) {}
};
KeyItem()
: type(Unknown)
, bits(0)
, caps(0)
{
}
};
class Key
{
public:
QList<KeyItem> keyItems; // first item is primary
QStringList userIds;
bool isTrusted;
class Key
{
public:
QList<KeyItem> keyItems; // first item is primary
QStringList userIds;
bool isTrusted;
Key() : isTrusted(false) {}
};
typedef QList<Key> KeyList;
Key()
: isTrusted(false)
{
}
};
typedef QList<Key> KeyList;
explicit GpgOp(const QString &bin, QObject *parent = 0);
~GpgOp();
explicit GpgOp(const QString &bin, QObject *parent = nullptr);
~GpgOp() override;
void reset();
void reset();
bool isActive() const;
Type op() const;
bool isActive() const;
Type op() const;
void setAsciiFormat(bool b);
void setDisableAgent(bool b);
void setAlwaysTrust(bool b);
void setKeyrings(const QString &pubfile, const QString &secfile); // for keylists and import
void setAsciiFormat(bool b);
void setDisableAgent(bool b);
void setAlwaysTrust(bool b);
void setKeyrings(const QString &pubfile, const QString &secfile); // for keylists and import
void doCheck();
void doSecretKeyringFile();
void doPublicKeyringFile();
void doSecretKeys();
void doPublicKeys();
void doEncrypt(const QStringList &recip_ids);
void doDecrypt();
void doSign(const QString &signer_id);
void doSignAndEncrypt(const QString &signer_id, const QStringList &recip_ids);
void doSignClearsign(const QString &signer_id);
void doSignDetached(const QString &signer_id);
void doVerify();
void doVerifyDetached(const QByteArray &sig);
void doImport(const QByteArray &in);
void doExport(const QString &key_id);
void doDeleteKey(const QString &key_fingerprint);
void doCheck();
void doSecretKeyringFile();
void doPublicKeyringFile();
void doSecretKeys();
void doPublicKeys();
void doEncrypt(const QStringList &recip_ids);
void doDecrypt();
void doSign(const QString &signer_id);
void doSignAndEncrypt(const QString &signer_id, const QStringList &recip_ids);
void doSignClearsign(const QString &signer_id);
void doSignDetached(const QString &signer_id);
void doVerify();
void doVerifyDetached(const QByteArray &sig);
void doImport(const QByteArray &in);
void doExport(const QString &key_id);
void doDeleteKey(const QString &key_fingerprint);
#ifdef QPIPE_SECURE
void submitPassphrase(const QCA::SecureArray &a);
void submitPassphrase(const QCA::SecureArray &a);
#else
void submitPassphrase(const QByteArray &a);
void submitPassphrase(const QByteArray &a);
#endif
void cardOkay();
void cardOkay();
// for encrypt, decrypt, sign, verify, export
QByteArray read();
void write(const QByteArray &in);
void endWrite();
// for encrypt, decrypt, sign, verify, export
QByteArray read();
void write(const QByteArray &in);
void endWrite();
QString readDiagnosticText();
QString readDiagnosticText();
// for synchronous operation
Event waitForEvent(int msecs = -1);
// for synchronous operation
Event waitForEvent(int msecs = -1);
// results
bool success() const;
Error errorCode() const;
KeyList keys() const; // Keys
QString keyringFile() const; // KeyringFile
QString encryptedToId() const; // Decrypt (for ErrorDecryptNoKey)
bool wasSigned() const; // Decrypt
QString signerId() const; // Verify
QDateTime timestamp() const; // Verify
VerifyResult verifyResult() const; // Verify
// results
bool success() const;
Error errorCode() const;
KeyList keys() const; // Keys
QString keyringFile() const; // KeyringFile
QString homeDir() const; // GnuPG home directory
QString encryptedToId() const; // Decrypt (for ErrorDecryptNoKey)
bool wasSigned() const; // Decrypt
QString signerId() const; // Verify
QDateTime timestamp() const; // Verify
VerifyResult verifyResult() const; // Verify
Q_SIGNALS:
void readyRead();
void bytesWritten(int bytes);
void finished();
void needPassphrase(const QString &keyId);
void needCard();
void readyReadDiagnosticText();
void readyRead();
void bytesWritten(int bytes);
void finished();
void needPassphrase(const QString &keyId);
void needCard();
void readyReadDiagnosticText();
private:
class Private;
friend class Private;
Private *d;
class Private;
friend class Private;
Private *d;
};
}

Some files were not shown because too many files have changed in this diff Show More