Compare commits

...

236 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
Harald Sitter
e44d0a335e bump version to 2.1.1 2015-10-02 11:35:20 +02:00
Harald Sitter
4f966b0217 Merge branch 'master' into qt5 2015-09-24 10:49:28 +02:00
Jan Grulich
66b9754170 Use Q_SLOTS/Q_SIGNALS instead of slots/signals in all headers from include dir
REVIEW:125289
2015-09-17 16:14:24 +02:00
Harald Sitter
088ff642fc Merge branch 'master' into qt5 2015-04-22 13:07:32 +02:00
Samuel Gaist
4fd11c444a Link against CoreFoundation rather than Carbon
Currently qca links to the Carbon framework for building however the mac
specific code don't use any Carbon classes but CoreFoundation. This patch
aims to update the code and build script to link to the more generic
CoreFoundation framework which may also allow to build it on iOS (not
verified).

REVIEW: 121703
2015-04-22 13:06:26 +02:00
Hrvoje Senjan
cc418554ad Merge remote-tracking branch 'origin/master' into qt5 2015-01-17 20:13:00 +01:00
Hrvoje Senjan
7207e6285e Add missing QIODevice include
Fixes build with Qt 5.5
2015-01-17 20:12:18 +01:00
Raphael Kubo da Costa
d4e9444f9d Do not end Cipher::Mode with a comma.
This solves a build failure with compilers such as GCC 4.2:
/usr/local/include/QtCrypto/qca_basic.h:598: error: comma at end of enumerator list

REVIEW: 122107
2015-01-17 15:21:20 +02:00
Harald Sitter
e40307d108 Merge remote-tracking branch 'origin/master' into qt5 2015-01-15 00:25:32 +01:00
Raphael Kubo da Costa
19aeaedd54 cmake: Make the check for QC_CERTSTORE_PATH actually work.
The previous code (present since the file was created) mixed different
checks that required different expansions:

* `if (ENV{foo})' will always evaluate to false even if $ENV{foo} is
  set, and may even be a CMake bug.
* `if (EXISTS ...)' expects an actual string, not an variable that has
  not been expanded.

It is not clear why the code expects QC_CERTSTORE_PATH to be an
environment variable instead of a regular variable passed to CMake in
the first place, but that can be changed in another commit.

REVIEW: 122062
2015-01-15 00:31:45 +02:00
Harald Sitter
b596e937b8 Revert "Revert "initialize QCA_SUFFIX cache with the possibly previously set SUFFIX""
This reverts commit c9f85b4dcab920d97a0959336ec71bc155209ccf.
2015-01-14 13:51:10 +01:00
Harald Sitter
b7f47694f8 Revert "Revert "properly support co-existing qt4 and qt5 versions""
This reverts commit 99128312fb91bc5f8e6320fe052bbaf7648102fe.
2015-01-14 13:51:07 +01:00
Ivan Romanov
99128312fb Revert "properly support co-existing qt4 and qt5 versions"
It's not properly. Martin Klapetek is not QCA developer. So it's not
correct that he said "Ship it!".

Properly way

cmake -DQCA_SUFFIX=qt5 ...

and in CMakeLists.txt of your project.

find_package(Qca NAMES Qca-qt5)

This reverts commit c32bc6f1bc9befe5f89d3572eb28e0d591a2e3b2.
2015-01-14 15:26:33 +05:00
Ivan Romanov
c9f85b4dca Revert "initialize QCA_SUFFIX cache with the possibly previously set SUFFIX"
I don't agree with this changes see https://git.reviewboard.kde.org/r/121168/
for details.

This reverts commit 3e3533b2753c8e47f0d22b77b564a0a6332cd5b8.
2015-01-14 15:24:11 +05:00
Harald Sitter
3e3533b275 initialize QCA_SUFFIX cache with the possibly previously set SUFFIX
this prevents us from unsetting what was previously set, making sure
the suffix is applied
2015-01-13 17:22:06 +01:00
Harald Sitter
c32bc6f1bc properly support co-existing qt4 and qt5 versions
- if QT4_BUILD is not defined *and* Qt5Core is found build with soname
  qca-qt5
- rename cmake package to reflect the suffix i.e. with a Qt5 build it is
  find_package(Qca-qt5) rather than find_package(Qca)
- the imported cmake target also reflects suffix so "Qca-qt5" is the
  cmake link target for qt5 and "Qca" for qt4 builds

this retains 100% compatibility with regular qca while also offering 100%
coinstallability of the qt5 build.

REVIEW: 121633
2014-12-28 14:26:50 +01:00
Harald Sitter
ffc53703ad put headers of a suffixed build in a suffixed directory
this makes the headers co-installable between a suffixed and regular
version

reviewed as part of r121323
2014-12-22 12:50:18 +01:00
Harald Sitter
4aae2dee34 prevent filewatches from emitting changes when there is no file
(this also fixes the flaky filewatch test that would fail for example on
 ubuntu launchpad builds)

it can happen that (supposedly for filesystem reasons) there are two
changes signals arriving in the watcher code, by the time the first arrives
the file would however already be deleted, by the time the second arrives
it would thus notify of changes to a file that does not exist which is
silly and causes problems with the filewatchtest as it uses signal emission
counting to verify the behavior.
to prevent this problem from popping up there is an additional save guard
in the file_changed slot that will ignore a change if the path in question
doesn't exist AND there is no file being watched by the watcher.

REVIEW: 121588
2014-12-19 16:47:40 +01:00
Harald Sitter
3b1bb19c7c add a reviewboardrc
REVIEW: 121325
2014-12-18 12:27:04 +01:00
Ivan Romanov
e57f8e7795 fixed array size checking
BUG: 341827
2014-12-13 01:54:53 +05:00
Harald Sitter
a67d31b1ec move QCA_CONFIG_NAME_BASE definition in the regular suffix if
(reviewed as part of r121323)
2014-12-02 13:32:09 +01:00
Harald Sitter
02be30908f fix library name in prf file to use the lib name variable
the lib name might be suffixed

(reviewed as part of r121323)
2014-12-02 13:29:52 +01:00
Ivan Romanov
9a9c16dfd1 cmake: fixed cmake config module when used QCA_SUFFIX 2014-11-29 00:57:31 +05:00
Ivan Romanov
98be0a1234 docs: fixed no images in docs when build out of source 2014-11-28 23:50:13 +05:00
Ivan Romanov
95223e9ee3 cmake: fixed warnings on android
do not use -Wcast-align on arm
2014-11-27 01:57:24 +05:00
Ivan Romanov
c8008de37b simplified md5_state_t and SHA1_CONTEXT internal structs
On arm is not correct to do int* = char* and throw warning. int must
be aligned unlike i686 and x86_64 archs. Anyway the old way to init
structs is not sane.
2014-11-27 01:55:47 +05:00
Ivan Romanov
20686e955c fixed compilation on android 2014-11-27 01:55:47 +05:00
Ivan Romanov
5d311c9219 cmake: build for android
Android uses .so as shared library suffix without version
2014-11-27 01:55:46 +05:00
Ivan Romanov
66447d0454 cmake: apply QCA_SUFFIX for cmake config module names 2014-11-22 06:30:07 +05:00
Ivan Romanov
2c58be171e cmake: warn user when QCA_SUFFIX is not set
Many linux distribution provides both version of Qt: Qt4 and Qt5.
These versions are binary is incompatible and any qt-based library
compiled against such Qt versions will be binary incompatible with
one another. In common case library name must not be related with
based libraries. In our case Linux users want to have both versions
QCA installed in their system. I will do not implicity rename Qt5
based QCA but just warn user and allow him explicity set QCA_SUFFIX.
2014-11-22 06:10:16 +05:00
Ivan Romanov
25860ff244 increased minimum cmake version
INCLUDE DESTINATION in install command was introduced only in CMake 2.8.12
2014-11-14 14:32:16 +05:00
Heiko Becker
593de6855a Fix build with libressl
libressl removed the SSL Compression functionality (which might
be considered insecure) and thus also compress_meth.
SSL_SESSION_get_compress_id is just a stub in libressl which always
returns 0 and in openssl it returns compress_meth.

REVIEW: 121107
2014-11-13 14:23:54 +05:00
Ivan Romanov
f8fe237c3c cmake: dropped dead variable 2014-11-13 02:13:50 +05:00
Ivan Romanov
72457bee3a qca-ossl: fixed compilation warnings 2014-11-13 02:13:50 +05:00
Ivan Romanov
8ffb52b439 cmake: pkg-config is not REQUIRED 2014-11-13 02:13:50 +05:00
Ivan Romanov
ca1667c118 dropped unused #include 2014-11-13 02:13:50 +05:00
283 changed files with 62307 additions and 62914 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

4
.reviewboardrc Normal file
View File

@ -0,0 +1,4 @@
REPOSITORY = "git://anongit.kde.org/qca"
REVIEWBOARD_URL = "https://git.reviewboard.kde.org"
TARGET_PEOPLE = "iromanov"
BRANCH = "master"

View File

@ -1,27 +1,29 @@
# Checking for user explicity defined CMAKE_INSTALL_PREFIX # Checking for user explicitly defined CMAKE_INSTALL_PREFIX
# It must be done before project(...) # It must be done before project(...)
if(NOT CMAKE_INSTALL_PREFIX) if(NOT CMAKE_INSTALL_PREFIX)
set(QCA_INSTALL_IN_QT_PREFIX ON) set(QCA_INSTALL_IN_QT_PREFIX ON)
# If CMAKE_INSTALL_PREFIX is set in cmake arguments # If CMAKE_INSTALL_PREFIX is set in cmake arguments
unset(CMAKE_INSTALL_PREFIX CACHE) 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) project(qca)
cmake_minimum_required(VERSION 2.6.0)
set(QCA_LIB_MAJOR_VERSION "2") set(QCA_LIB_MAJOR_VERSION "2")
set(QCA_LIB_MINOR_VERSION "1") set(QCA_LIB_MINOR_VERSION "3")
set(QCA_LIB_PATCH_VERSION "0") set(QCA_LIB_PATCH_VERSION "3")
# Do not automatically link Qt executables to qtmain target on Windows. #if(POLICY CMP0042)
# QCA exucatables use console mode only. Not need to link against # cmake_policy(SET CMP0042 OLD)
# qtmain.lib. #endif()
cmake_policy(SET CMP0020 OLD)
option(QT6 "Build with Qt 6" OFF)
option(BUILD_TESTS "Create test" ON) option(BUILD_TESTS "Create test" ON)
option(BUILD_TOOLS "Compile mozcerts and qcatool" 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)") set(BUILD_PLUGINS "auto" CACHE STRING "Plugins for building (also possible values: none, all and auto)")
# BUILD_SHARED_LIBS is cmake variable. Need to change default value.
option(BUILD_SHARED_LIBS "Build shared library" ON) option(BUILD_SHARED_LIBS "Build shared library" ON)
option(DEVELOPER_MODE "Special developer mode" OFF) option(DEVELOPER_MODE "Special developer mode" OFF)
@ -36,43 +38,32 @@ find_package(Doxygen)
string(TOLOWER "${BUILD_PLUGINS}" BUILD_PLUGINS) string(TOLOWER "${BUILD_PLUGINS}" BUILD_PLUGINS)
if(NOT BUILD_PLUGINS) if(NOT BUILD_PLUGINS)
set(BUILD_PLUGINS "none") set(BUILD_PLUGINS "none")
endif(NOT BUILD_PLUGINS) endif()
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules" ) set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules" )
option(QT4_BUILD "Force building with Qt4 even if Qt5 is found") # Do not automatically link Qt executables to qtmain target on Windows.
if (NOT QT4_BUILD) # QCA exucatables use console mode only. Not need to link against qtmain.lib.
find_package(Qt5Core QUIET) if(QT6)
mark_as_advanced(Qt5Core_DIR) 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() endif()
set(CMAKE_AUTOMOC ON)
include(QcaMacro) include(QcaMacro)
include(GNUInstallDirs)
if (Qt5Core_FOUND) setup_qt_dirs()
message(STATUS "Building with Qt5 support") if(QT6)
# Got from ECM set(QCA_QT_PC_VERSION "Qt6Core")
# Distros have no ECM. So I just copied required cmake modules. set(QCA_SUFFIX "qt6")
find_package(Qt5Transitional REQUIRED Core Network)
include(ECMQt4To5Porting)
include(GNUInstallDirs)
setup_qt5_dirs()
set(QCA_QT_PC_VERSION "Qt5Core")
else() else()
set(QT_MIN_VERSION "4.7.0") set(QCA_QT_PC_VERSION "Qt5Core")
set(QT_USE_IMPORTED_TARGETS ON) set(QCA_SUFFIX "qt5")
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() endif()
# QCA can be shared but plugins will be static # QCA can be shared but plugins will be static
@ -81,22 +72,24 @@ if(NOT BUILD_SHARED_LIBS OR QT_IS_STATIC)
set(STATIC_PLUGINS ON) set(STATIC_PLUGINS ON)
add_definitions(-DQT_STATICPLUGIN) add_definitions(-DQT_STATICPLUGIN)
set(PLUGIN_TYPE "STATIC") set(PLUGIN_TYPE "STATIC")
else(NOT BUILD_SHARED_LIBS OR QT_IS_STATIC) else()
set(PLUGIN_TYPE "MODULE") set(PLUGIN_TYPE "MODULE")
endif(NOT BUILD_SHARED_LIBS OR QT_IS_STATIC) endif()
set(QCA_SUFFIX "" CACHE STRING "QCA common suffix") set(QCA_SUFFIX "${QCA_SUFFIX}" CACHE STRING "QCA common suffix")
if(QCA_SUFFIX) if(QCA_SUFFIX)
set(QCA_LIB_NAME qca-${QCA_SUFFIX}) set(QCA_LIB_NAME qca-${QCA_SUFFIX})
set(QCA_TOOL_NAME qcatool-${QCA_SUFFIX}) set(QCA_TOOL_NAME qcatool-${QCA_SUFFIX})
set(MOZCERTS_NAME mozcerts-${QCA_SUFFIX}) set(MOZCERTS_NAME mozcerts-${QCA_SUFFIX})
set(QCA_PC_NAME qca2-${QCA_SUFFIX}.pc) set(QCA_PC_NAME qca2-${QCA_SUFFIX}.pc)
else(QCA_SUFFIX) set(QCA_CONFIG_NAME_BASE "Qca-${QCA_SUFFIX}")
else()
set(QCA_LIB_NAME qca) set(QCA_LIB_NAME qca)
set(QCA_TOOL_NAME qcatool) set(QCA_TOOL_NAME qcatool)
set(MOZCERTS_NAME mozcerts) set(MOZCERTS_NAME mozcerts)
set(QCA_PC_NAME qca2.pc) set(QCA_PC_NAME qca2.pc)
endif(QCA_SUFFIX) set(QCA_CONFIG_NAME_BASE "Qca")
endif()
set(QCA_LIB_VERSION_STRING "${QCA_LIB_MAJOR_VERSION}.${QCA_LIB_MINOR_VERSION}.${QCA_LIB_PATCH_VERSION}") set(QCA_LIB_VERSION_STRING "${QCA_LIB_MAJOR_VERSION}.${QCA_LIB_MINOR_VERSION}.${QCA_LIB_PATCH_VERSION}")
@ -107,17 +100,42 @@ if (WIN32)
add_definitions(-DWIN32_LEAN_AND_MEAN) add_definitions(-DWIN32_LEAN_AND_MEAN)
elseif (APPLE) elseif (APPLE)
set(CMAKE_DEBUG_POSTFIX "_debug") 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) if (CMAKE_SYSTEM_NAME MATCHES Linux)
add_definitions (-D_BSD_SOURCE) add_definitions (-D_DEFAULT_SOURCE)
set ( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-long-long -ansi -Wundef -Wcast-align -Werror-implicit-function-declaration -Wchar-subscripts -Wall -W -Wpointer-arith -Wwrite-strings -Wformat-security -Wmissing-format-attribute -fno-common") # on arm -Wcast-align throws many internal qt warning
set ( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wnon-virtual-dtor -Wno-long-long -ansi -Wundef -Wcast-align -Wchar-subscripts -Wall -W -Wpointer-arith -Wwrite-strings -Wformat-security -fno-check-new -fno-common") if(NOT CMAKE_SYSTEM_PROCESSOR MATCHES "^arm")
endif (CMAKE_SYSTEM_NAME MATCHES Linux) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wcast-align")
endif (CMAKE_COMPILER_IS_GNUCXX) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wcast-align")
endif()
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/") include_directories("include/QtCrypto/")
# for generated files # for generated files
include_directories(${CMAKE_BINARY_DIR}) include_directories(${CMAKE_BINARY_DIR})
@ -155,11 +173,16 @@ if( QCA_INSTALL_IN_QT_PREFIX )
set(QCA_BINARY_INSTALL_DIR "${QT_BINARY_DIR}" CACHE PATH "Directory where qca plugins will install") set(QCA_BINARY_INSTALL_DIR "${QT_BINARY_DIR}" CACHE PATH "Directory where qca plugins will install")
set(QCA_LIBRARY_INSTALL_DIR "${QT_LIBRARY_DIR}" CACHE PATH "Directory where qca library will install") set(QCA_LIBRARY_INSTALL_DIR "${QT_LIBRARY_DIR}" CACHE PATH "Directory where qca library will install")
set(QCA_FEATURE_INSTALL_DIR "${QT_MKSPECS_DIR}/features" CACHE PATH "Directory where qca feature file will install") set(QCA_FEATURE_INSTALL_DIR "${QT_MKSPECS_DIR}/features" CACHE PATH "Directory where qca feature file will install")
set(QCA_INCLUDE_INSTALL_DIR "${QT_HEADERS_DIR}" CACHE PATH "Directory where qca public headers will install") if(NOT QCA_SUFFIX)
set(QCA_PRIVATE_INCLUDE_INSTALL_DIR "${QT_HEADERS_DIR}" CACHE PATH "Directory where qca headers will install") set(QCA_INCLUDE_INSTALL_DIR "${QT_HEADERS_DIR}" CACHE PATH "Directory where qca public headers will install")
set(QCA_PRIVATE_INCLUDE_INSTALL_DIR "${QT_HEADERS_DIR}" CACHE PATH "Directory where qca headers will install")
else()
set(QCA_INCLUDE_INSTALL_DIR "${QT_HEADERS_DIR}/${QCA_CONFIG_NAME_BASE}" CACHE PATH "Directory where qca public headers will install")
set(QCA_PRIVATE_INCLUDE_INSTALL_DIR "${QT_HEADERS_DIR}/${QCA_CONFIG_NAME_BASE}" CACHE PATH "Directory where qca headers will install")
endif()
set(QCA_DOC_INSTALL_DIR "${QT_DOC_DIR}/html/qca/" CACHE PATH "Directory where qca documentation will install") 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") 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 # Cmake says nothing about LIB_SUFFIX
# de facto it is a standard way to specify lib suffix on many distros # 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)" ) set(LIB_SUFFIX "" CACHE STRING "Define suffix of directory name (32/64)" )
@ -170,16 +193,27 @@ else( QCA_INSTALL_IN_QT_PREFIX )
set(QCA_BINARY_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/bin" CACHE PATH "Directory where qca plugins will install") set(QCA_BINARY_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/bin" CACHE PATH "Directory where qca plugins will install")
set(QCA_LIBRARY_INSTALL_DIR "${LIB_INSTALL_DIR}" CACHE PATH "Directory where qca library will install") set(QCA_LIBRARY_INSTALL_DIR "${LIB_INSTALL_DIR}" CACHE PATH "Directory where qca library will install")
set(QCA_FEATURE_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/mkspecs/features" CACHE PATH "Directory where qca feature file will install") set(QCA_FEATURE_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/mkspecs/features" CACHE PATH "Directory where qca feature file will install")
set(QCA_INCLUDE_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/include" CACHE PATH "Directory where qca public headers will install") if(NOT QCA_SUFFIX)
set(QCA_PRIVATE_INCLUDE_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/include" CACHE PATH "Directory where qca headers will install") set(QCA_INCLUDE_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/include" CACHE PATH "Directory where qca public headers will install")
set(QCA_PRIVATE_INCLUDE_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/include" CACHE PATH "Directory where qca headers will install")
else()
set(QCA_INCLUDE_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/include/${QCA_CONFIG_NAME_BASE}" CACHE PATH "Directory where qca public headers will install")
set(QCA_PRIVATE_INCLUDE_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/include/${QCA_CONFIG_NAME_BASE}" CACHE PATH "Directory where qca headers will install")
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_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") 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") set(PKGCONFIG_INSTALL_PREFIX "${QCA_LIBRARY_INSTALL_DIR}/pkgconfig" CACHE PATH "Base directory for pkgconfig files")
normalize_path(QCA_PREFIX_INSTALL_DIR) 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 # check for oportunity to use relative paths
option(USE_RELATIVE_PATHS "Try to make relocatable package") option(USE_RELATIVE_PATHS "Try to make relocatable package")
@ -205,19 +239,21 @@ endforeach()
if(NOT WIN32) if(NOT WIN32)
if(OSX_FRAMEWORK) 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}") set(PKGCONFIG_LIBS "-F\${libdir} -framework ${QCA_LIB_NAME}")
else() else()
set(PKGCONFIG_CFLAGS "-I\${includedir}") set(PKGCONFIG_CFLAGS "-I\${includedir}")
set(PKGCONFIG_LIBS "-L\${libdir} -l${QCA_LIB_NAME}") set(PKGCONFIG_LIBS "-L\${libdir} -l${QCA_LIB_NAME}")
endif() endif()
# qca2.pc uses absolute paths. So it must be there. Don't rellocate this. if(NOT QT6)
configure_file("qca2.pc.cmake" "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/pkgconfig/${QCA_PC_NAME}" @ONLY) # qca2.pc uses absolute paths. So it must be there. Don't rellocate this.
if(NOT DEVELOPER_MODE) configure_file("qca2.pc.cmake" "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/pkgconfig/${QCA_PC_NAME}" @ONLY)
install(FILES "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/pkgconfig/${QCA_PC_NAME}" DESTINATION ${PKGCONFIG_INSTALL_PREFIX}) if(NOT DEVELOPER_MODE)
install(FILES "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/pkgconfig/${QCA_PC_NAME}" DESTINATION ${PKGCONFIG_INSTALL_PREFIX})
endif()
endif() endif()
endif(NOT WIN32) endif()
# strip CMAKE_INSTALL_PREFIX in all paths # strip CMAKE_INSTALL_PREFIX in all paths
if(USE_RELATIVE_PATHS) if(USE_RELATIVE_PATHS)
@ -252,23 +288,19 @@ Plugins=${CMAKE_BINARY_DIR}/lib/${QCA_LIB_NAME}
endif() endif()
if (APPLE) if (APPLE)
find_package(Carbon REQUIRED)
set(CMAKE_INSTALL_NAME_DIR ${QCA_LIBRARY_INSTALL_DIR})
set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE) set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
endif (APPLE) endif()
message(STATUS "Checking for certstore..") message(STATUS "Checking for certstore..")
# fixme add OR mac # fixme add OR mac
if( WIN32 ) if( WIN32 )
# USE BUILTIN # USE BUILTIN
else ( WIN32 ) else()
if ( ENV{QC_CERTSTORE_PATH} ) if ( DEFINED ENV{QC_CERTSTORE_PATH} )
if(EXISTS ENV{QC_CERTSTORE_PATH}) if(EXISTS $ENV{QC_CERTSTORE_PATH})
set( qca_CERTSTORE $ENV{QC_CERTSTORE_PATH}) set( qca_CERTSTORE $ENV{QC_CERTSTORE_PATH})
else(EXISTS ENV{QC_CERTSTORE_PATH}) endif()
# path to try else()
endif(EXISTS ENV{QC_CERTSTORE_PATH})
else( ENV{QC_CERTSTORE_PATH} )
set( toTry set( toTry
"/etc/ssl/certs/ca-certificates.crt" "/etc/ssl/certs/ca-certificates.crt"
"/usr/share/ssl/cert.pem" "/usr/share/ssl/cert.pem"
@ -280,28 +312,28 @@ else ( WIN32 )
foreach (_current_try ${toTry}) foreach (_current_try ${toTry})
if(EXISTS ${_current_try}) if(EXISTS ${_current_try})
set( qca_CERTSTORE ${_current_try}) set( qca_CERTSTORE ${_current_try})
endif(EXISTS ${_current_try}) endif()
endforeach (_current_try) endforeach (_current_try)
endif( ENV{QC_CERTSTORE_PATH} ) endif()
endif(WIN32) endif()
if (qca_CERTSTORE) if (qca_CERTSTORE)
message(STATUS "Found system certstore") message(STATUS "Found system certstore")
else (qca_CERTSTORE) else()
message(STATUS "Using built in certstore.") message(STATUS "Using built in certstore.")
set( qca_CERTSTORE "${CMAKE_CURRENT_SOURCE_DIR}/certs/rootcerts.pem") set( qca_CERTSTORE "${CMAKE_CURRENT_SOURCE_DIR}/certs/rootcerts.pem")
# note that INSTALL_FILES targets are relative to the current installation prefix... # note that INSTALL_FILES targets are relative to the current installation prefix...
if(NOT DEVELOPER_MODE) if(NOT DEVELOPER_MODE)
install(FILES "${qca_CERTSTORE}" DESTINATION "${QCA_PREFIX_INSTALL_DIR}/certs") install(FILES "${qca_CERTSTORE}" DESTINATION "${QCA_PREFIX_INSTALL_DIR}/certs")
endif() endif()
endif (qca_CERTSTORE) endif()
message(STATUS "certstore path: " ${qca_CERTSTORE}) message(STATUS "certstore path: " ${qca_CERTSTORE})
add_definitions( -DQCA_SYSTEMSTORE_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( 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/qca.h
${qca_INCLUDEDIR}/QtCrypto/qcaprovider.h ${qca_INCLUDEDIR}/QtCrypto/qcaprovider.h
${qca_INCLUDEDIR}/QtCrypto/QtCrypto ${qca_INCLUDEDIR}/QtCrypto/QtCrypto
@ -322,11 +354,13 @@ set( public_HEADERS
set( qca_HEADERS ${private_HEADERS} ${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 QT6)
if(NOT DEVELOPER_MODE) configure_file("crypto.prf.cmake" "${CMAKE_BINARY_DIR}/mkspecs/features/crypto.prf" @ONLY)
install(FILES "${CMAKE_BINARY_DIR}/mkspecs/features/crypto.prf" DESTINATION "${QCA_FEATURE_INSTALL_DIR}") if(NOT DEVELOPER_MODE)
install(FILES "${CMAKE_BINARY_DIR}/mkspecs/features/crypto.prf" DESTINATION "${QCA_FEATURE_INSTALL_DIR}")
endif()
endif() endif()
configure_file(man/qcatool.1 "${CMAKE_BINARY_DIR}/share/man/man1/${QCA_TOOL_NAME}.1" COPYONLY) configure_file(man/qcatool.1 "${CMAKE_BINARY_DIR}/share/man/man1/${QCA_TOOL_NAME}.1" COPYONLY)
@ -346,37 +380,37 @@ if(STATIC_PLUGINS)
if(WITH_${PLUGIN}_PLUGIN_INTERNAL) if(WITH_${PLUGIN}_PLUGIN_INTERNAL)
string(REPLACE "-" "_" IMPORT_NAME "qca-${PLUGIN}") string(REPLACE "-" "_" IMPORT_NAME "qca-${PLUGIN}")
file(APPEND "${CMAKE_BINARY_DIR}/import_plugins.h" "Q_IMPORT_PLUGIN(${IMPORT_NAME})\n") 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) endforeach(PLUGIN IN LISTS PLUGINS)
endif(STATIC_PLUGINS) endif()
if(BUILD_TESTS) if(BUILD_TESTS)
enable_testing() enable_testing()
add_subdirectory(unittest) add_subdirectory(unittest)
add_subdirectory(examples) add_subdirectory(examples)
endif(BUILD_TESTS) endif()
if(BUILD_TOOLS) if(BUILD_TOOLS)
add_subdirectory(tools) add_subdirectory(tools)
endif(BUILD_TOOLS) endif()
if(DOXYGEN_FOUND) #if(DOXYGEN_FOUND)
configure_file(${CMAKE_SOURCE_DIR}/Doxyfile.in ${CMAKE_BINARY_DIR}/Doxyfile @ONLY) # configure_file(${CMAKE_SOURCE_DIR}/Doxyfile.in ${CMAKE_BINARY_DIR}/Doxyfile @ONLY)
add_custom_target(doc # add_custom_target(doc
${DOXYGEN_EXECUTABLE} ${CMAKE_BINARY_DIR}/Doxyfile # ${DOXYGEN_EXECUTABLE} ${CMAKE_BINARY_DIR}/Doxyfile
COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/images # COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/docs/pics
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}/docs/pics/qca-arch.eps ${CMAKE_BINARY_DIR}/docs/pics/qca-arch.eps
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_SOURCE_DIR}/images/qca-arch.png ${CMAKE_BINARY_DIR}/images/qca-arch.png # 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} # WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
COMMENT "Generating API documentation with Doxygen" VERBATIM) # COMMENT "Generating API documentation with Doxygen" VERBATIM)
endif(DOXYGEN_FOUND) #endif()
include(CMakePackageConfigHelpers) include(CMakePackageConfigHelpers)
configure_package_config_file( configure_package_config_file(
"${CMAKE_CURRENT_SOURCE_DIR}/QcaConfig.cmake.in" "${CMAKE_CURRENT_SOURCE_DIR}/QcaConfig.cmake.in"
"${CMAKE_CURRENT_BINARY_DIR}/lib/cmake/Qca/QcaConfig.cmake" "${CMAKE_CURRENT_BINARY_DIR}/lib/cmake/${QCA_CONFIG_NAME_BASE}/${QCA_CONFIG_NAME_BASE}Config.cmake"
INSTALL_DESTINATION ${QCA_LIBRARY_INSTALL_DIR}/cmake/Qca INSTALL_DESTINATION ${QCA_LIBRARY_INSTALL_DIR}/cmake/${QCA_CONFIG_NAME_BASE}
) )
write_basic_config_version_file("${CMAKE_CURRENT_BINARY_DIR}/lib/cmake/Qca/QcaConfigVersion.cmake" VERSION ${QCA_LIB_VERSION_STRING} COMPATIBILITY AnyNewerVersion) write_basic_config_version_file("${CMAKE_CURRENT_BINARY_DIR}/lib/cmake/${QCA_CONFIG_NAME_BASE}/${QCA_CONFIG_NAME_BASE}ConfigVersion.cmake" VERSION ${QCA_LIB_VERSION_STRING} COMPATIBILITY AnyNewerVersion)
if(NOT DEVELOPER_MODE) if(NOT DEVELOPER_MODE)
@ -398,7 +432,7 @@ if(NOT DEVELOPER_MODE)
message("!! you MUST explicity define CMAKE_INSTALL_PREFIX !!") message("!! you MUST explicity define CMAKE_INSTALL_PREFIX !!")
message("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!") message("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")
message("${ESCAPE}[0m") message("${ESCAPE}[0m")
endif(QCA_INSTALL_IN_QT_PREFIX) endif()
message("") message("")
if(USE_RELATIVE_PATHS) if(USE_RELATIVE_PATHS)
@ -434,10 +468,25 @@ if(NOT DEVELOPER_MODE)
endif() endif()
message("") message("")
install(EXPORT QCATargets DESTINATION ${QCA_LIBRARY_INSTALL_DIR}/cmake/Qca FILE QcaTargets.cmake) if(UNIX AND NOT APPLE)
if(NOT QCA_SUFFIX)
message("${ESCAPE}[31mYou don't have QCA_SUFFIX set. Please note that the recommended way of")
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()
install(EXPORT ${QCA_CONFIG_NAME_BASE}Targets DESTINATION ${QCA_LIBRARY_INSTALL_DIR}/cmake/${QCA_CONFIG_NAME_BASE} FILE ${QCA_CONFIG_NAME_BASE}Targets.cmake)
install(FILES install(FILES
"${CMAKE_CURRENT_BINARY_DIR}/lib/cmake/Qca/QcaConfig.cmake" "${CMAKE_CURRENT_BINARY_DIR}/lib/cmake/${QCA_CONFIG_NAME_BASE}/${QCA_CONFIG_NAME_BASE}Config.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/lib/cmake/Qca/QcaConfigVersion.cmake" "${CMAKE_CURRENT_BINARY_DIR}/lib/cmake/${QCA_CONFIG_NAME_BASE}/${QCA_CONFIG_NAME_BASE}ConfigVersion.cmake"
DESTINATION ${QCA_LIBRARY_INSTALL_DIR}/cmake/Qca DESTINATION ${QCA_LIBRARY_INSTALL_DIR}/cmake/${QCA_CONFIG_NAME_BASE}
) )
endif() endif()

View File

@ -567,7 +567,7 @@ EXAMPLE_RECURSIVE = NO
# directories that contain image that are included in the documentation (see # directories that contain image that are included in the documentation (see
# the \image command). # the \image command).
IMAGE_PATH = images IMAGE_PATH = @CMAKE_SOURCE_DIR@/docs/pics
# The INPUT_FILTER tag can be used to specify a program that doxygen should # 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 # 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. # 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. # 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 # 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 # doxygen's preprocessor will remove all function-like macros that are alone

11
INSTALL
View File

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

View File

@ -150,9 +150,9 @@
\subsection qca2code Releases \subsection qca2code Releases
The latest release packages can be found in the 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. further information about %QCA releases.
\subsection qca2dev Current development \subsection qca2dev Current development
@ -163,12 +163,12 @@
to build and use %QCA. to build and use %QCA.
The Git code can be browsed 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> via the web</a>
Use Use
\verbatim \verbatim
git clone git://anongit.kde.org/qca.git git clone https://invent.kde.org/libraries/qca.git
\endverbatim \endverbatim
to get the latest sources. to get the latest sources.
*/ */

View File

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

77
README
View File

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

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 rootcerts.pem is created by qca/tools/mozcerts
File: mozilla/security/nss/lib/ckfw/builtins/certdata.txt File: https://hg.mozilla.org/mozilla-central/log/tip/security/nss/lib/ckfw/builtins/certdata.txt
Date: January 15th, 2009 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

@ -1,13 +0,0 @@
# Copyright (c) 2006, Benjamin Reed, <ranger@befunk.com>
#
# Redistribution and use is allowed according to the terms of the BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
INCLUDE(CMakeFindFrameworks)
CMAKE_FIND_FRAMEWORKS(Carbon)
if (Carbon_FRAMEWORKS)
set(CARBON_LIBRARY "-framework Carbon" CACHE FILEPATH "Carbon framework" FORCE)
set(CARBON_FOUND 1)
endif (Carbon_FRAMEWORKS)

View File

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

@ -21,19 +21,19 @@ if(PKCS11H_INCLUDE_DIRS AND PKCS11H_LDFLAGS)
else() else()
if(NOT WIN32) if(NOT WIN32)
find_package(PkgConfig REQUIRED) find_package(PkgConfig)
pkg_search_module(PKCS11H libpkcs11-helper-1) pkg_search_module(PKCS11H libpkcs11-helper-1)
endif(NOT WIN32) endif()
if (PKCS11H_FOUND) if (PKCS11H_FOUND)
if (NOT Pkcs11Helper_FIND_QUIETLY) if (NOT Pkcs11Helper_FIND_QUIETLY)
message(STATUS "Found pkcs11-helper: ${PKCS11H_LDFLAGS}") message(STATUS "Found pkcs11-helper: ${PKCS11H_LDFLAGS}")
endif (NOT Pkcs11Helper_FIND_QUIETLY) endif()
else (PKCS11H_FOUND) else()
if (Pkcs11Helper_FIND_REQUIRED) if (Pkcs11Helper_FIND_REQUIRED)
message(FATAL_ERROR "Could NOT find pkcs11-helper") message(FATAL_ERROR "Could NOT find pkcs11-helper")
endif (Pkcs11Helper_FIND_REQUIRED) endif()
endif (PKCS11H_FOUND) endif()
mark_as_advanced(PKCS11H_INCLUDE_DIRS PKCS11H_LDFLAGS PKCS11H_CFLAGS_OTHER) 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) if (SASL2_INCLUDE_DIR)
# Already in cache, be silent # Already in cache, be silent
set(SASL2_FIND_QUIETLY TRUE) set(SASL2_FIND_QUIETLY TRUE)
endif (SASL2_INCLUDE_DIR) endif()
FIND_PATH(SASL2_INCLUDE_DIR sasl/sasl.h) 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) if (SASL2_INCLUDE_DIR AND SASL2_LIBRARIES)
set(SASL2_FOUND TRUE) set(SASL2_FOUND TRUE)
endif (SASL2_INCLUDE_DIR AND SASL2_LIBRARIES) endif()
if (SASL2_FOUND) if (SASL2_FOUND)
if (NOT Sasl2_FIND_QUIETLY) if (NOT Sasl2_FIND_QUIETLY)
message(STATUS "Found Sasl2: ${SASL2_LIBRARIES}") message(STATUS "Found Sasl2: ${SASL2_LIBRARIES}")
endif (NOT Sasl2_FIND_QUIETLY) endif()
else (SASL2_FOUND) else()
if (Sasl2_FIND_REQUIRED) if (Sasl2_FIND_REQUIRED)
message(FATAL_ERROR "Could not find sasl2 libraries") message(FATAL_ERROR "Could not find sasl2 libraries")
endif (Sasl2_FIND_REQUIRED) endif()
endif (SASL2_FOUND) endif()
MARK_AS_ADVANCED(SASL2_INCLUDE_DIR SASL2_LIBRARIES) MARK_AS_ADVANCED(SASL2_INCLUDE_DIR SASL2_LIBRARIES)

View File

@ -1,63 +1,28 @@
IF (Qt5Core_FOUND) MACRO(SETUP_QT_DIRS)
# FindQt4.cmake wasn't used, so define it here if(QT6)
MACRO (QT4_GET_MOC_INC_DIRS _moc_INC_DIRS) GET_TARGET_PROPERTY(QMAKE_EXECUTABLE Qt6::qmake LOCATION)
SET(${_moc_INC_DIRS}) else()
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)
GET_TARGET_PROPERTY(QMAKE_EXECUTABLE ${Qt5Core_QMAKE_EXECUTABLE} LOCATION) GET_TARGET_PROPERTY(QMAKE_EXECUTABLE ${Qt5Core_QMAKE_EXECUTABLE} LOCATION)
EXEC_PROGRAM( ${QMAKE_EXECUTABLE} ARGS "-query QT_INSTALL_LIBS" OUTPUT_VARIABLE QT_LIBRARY_DIR ) endif()
EXEC_PROGRAM( ${QMAKE_EXECUTABLE} ARGS "-query QT_INSTALL_PREFIX" OUTPUT_VARIABLE QT_PREFIX_DIR ) EXEC_PROGRAM( ${QMAKE_EXECUTABLE} ARGS "-query QT_INSTALL_LIBS" OUTPUT_VARIABLE QT_LIBRARY_DIR )
EXEC_PROGRAM( ${QMAKE_EXECUTABLE} ARGS "-query QT_INSTALL_PLUGINS" OUTPUT_VARIABLE QT_PLUGINS_DIR ) EXEC_PROGRAM( ${QMAKE_EXECUTABLE} ARGS "-query QT_INSTALL_PREFIX" OUTPUT_VARIABLE QT_PREFIX_DIR )
EXEC_PROGRAM( ${QMAKE_EXECUTABLE} ARGS "-query QT_INSTALL_BINS" OUTPUT_VARIABLE QT_BINARY_DIR ) EXEC_PROGRAM( ${QMAKE_EXECUTABLE} ARGS "-query QT_INSTALL_PLUGINS" OUTPUT_VARIABLE QT_PLUGINS_DIR )
EXEC_PROGRAM( ${QMAKE_EXECUTABLE} ARGS "-query QT_INSTALL_HEADERS" OUTPUT_VARIABLE QT_HEADERS_DIR ) EXEC_PROGRAM( ${QMAKE_EXECUTABLE} ARGS "-query QT_INSTALL_BINS" OUTPUT_VARIABLE QT_BINARY_DIR )
EXEC_PROGRAM( ${QMAKE_EXECUTABLE} ARGS "-query QT_INSTALL_DOCS" OUTPUT_VARIABLE QT_DOC_DIR ) EXEC_PROGRAM( ${QMAKE_EXECUTABLE} ARGS "-query QT_INSTALL_HEADERS" OUTPUT_VARIABLE QT_HEADERS_DIR )
EXEC_PROGRAM( ${QMAKE_EXECUTABLE} ARGS "-query QT_INSTALL_DATA" OUTPUT_VARIABLE QT_DATA_DIR ) EXEC_PROGRAM( ${QMAKE_EXECUTABLE} ARGS "-query QT_INSTALL_DOCS" OUTPUT_VARIABLE QT_DOC_DIR )
EXEC_PROGRAM( ${QMAKE_EXECUTABLE} ARGS "-query QT_INSTALL_ARCHDATA" OUTPUT_VARIABLE QT_ARCHDATA_DIR ) EXEC_PROGRAM( ${QMAKE_EXECUTABLE} ARGS "-query QT_INSTALL_DATA" OUTPUT_VARIABLE QT_DATA_DIR )
SET( QT_MKSPECS_DIR "${QT_ARCHDATA_DIR}/mkspecs" ) EXEC_PROGRAM( ${QMAKE_EXECUTABLE} ARGS "-query QT_HOST_DATA" OUTPUT_VARIABLE QT_ARCHDATA_DIR )
ENDMACRO(SETUP_QT5_DIRS) SET( QT_MKSPECS_DIR "${QT_ARCHDATA_DIR}/mkspecs" )
ELSE (Qt5Core_FOUND) ENDMACRO(SETUP_QT_DIRS)
# 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)
macro(set_enabled_plugin PLUGIN ENABLED) macro(set_enabled_plugin PLUGIN ENABLED)
# To nice looks # To nice looks
if(ENABLED) if(ENABLED)
set(ENABLED "on") set(ENABLED "on")
else(ENABLED) else()
set(ENABLED "off") set(ENABLED "off")
endif(ENABLED) endif()
set(WITH_${PLUGIN}_PLUGIN_INTERNAL ${ENABLED} CACHE INTERNAL "") set(WITH_${PLUGIN}_PLUGIN_INTERNAL ${ENABLED} CACHE INTERNAL "")
endmacro(set_enabled_plugin) endmacro(set_enabled_plugin)
@ -72,7 +37,6 @@ endmacro(disable_plugin)
# it used to build examples and tools # it used to build examples and tools
macro(target_link_qca_libraries TARGET) macro(target_link_qca_libraries TARGET)
# Link with QCA library # Link with QCA library
target_link_libraries(${TARGET} ${QT_QTCORE_LIBRARY})
target_link_libraries(${TARGET} ${QCA_LIB_NAME}) target_link_libraries(${TARGET} ${QCA_LIB_NAME})
# Statically link with all enabled QCA plugins # Statically link with all enabled QCA plugins
@ -82,15 +46,19 @@ macro(target_link_qca_libraries TARGET)
# Check plugin for enabled # Check plugin for enabled
if(WITH_${PLUGIN}_PLUGIN_INTERNAL) if(WITH_${PLUGIN}_PLUGIN_INTERNAL)
target_link_libraries(${TARGET} qca-${PLUGIN}) target_link_libraries(${TARGET} qca-${PLUGIN})
endif(WITH_${PLUGIN}_PLUGIN_INTERNAL) endif()
endforeach(PLUGIN) endforeach(PLUGIN)
endif(STATIC_PLUGINS) endif()
endmacro(target_link_qca_libraries) endmacro(target_link_qca_libraries)
# it used to build unittests # it used to build unittests
macro(target_link_qca_test_libraries TARGET) macro(target_link_qca_test_libraries TARGET)
target_link_qca_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) endmacro(target_link_qca_test_libraries)
# it used to build unittests # it used to build unittests
@ -109,7 +77,7 @@ macro(install_pdb TARGET INSTALL_PATH)
get_target_property(LOCATION ${TARGET} LOCATION_RELWITHDEBINFO) get_target_property(LOCATION ${TARGET} LOCATION_RELWITHDEBINFO)
string(REGEX REPLACE "\\.[^.]*$" ".pdb" LOCATION "${LOCATION}") string(REGEX REPLACE "\\.[^.]*$" ".pdb" LOCATION "${LOCATION}")
install(FILES ${LOCATION} DESTINATION ${INSTALL_PATH} CONFIGURATIONS RelWithDebInfo) install(FILES ${LOCATION} DESTINATION ${INSTALL_PATH} CONFIGURATIONS RelWithDebInfo)
endif(MSVC) endif()
endmacro(install_pdb) endmacro(install_pdb)
macro(normalize_path PATH) 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") if (NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
message(FATAL_ERROR "Cannot find install manifest: \"@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) file(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files)
string(REGEX REPLACE "\n" ";" files "${files}") string(REGEX REPLACE "\n" ";" files "${files}")
@ -19,8 +19,8 @@ foreach (file ${files})
) )
if(NOT ${rm_retval} EQUAL 0) if(NOT ${rm_retval} EQUAL 0)
message(FATAL_ERROR "Problem when removing \"$ENV{DESTDIR}${file}\"") message(FATAL_ERROR "Problem when removing \"$ENV{DESTDIR}${file}\"")
endif (NOT ${rm_retval} EQUAL 0) endif()
else (EXISTS "$ENV{DESTDIR}${file}") else()
message(STATUS "File \"$ENV{DESTDIR}${file}\" does not exist.") message(STATUS "File \"$ENV{DESTDIR}${file}\" does not exist.")
endif (EXISTS "$ENV{DESTDIR}${file}") endif()
endforeach(file) endforeach(file)

View File

@ -5,21 +5,21 @@ CONFIG *= qt
LINKAGE = LINKAGE =
exists($$QCA_LIBDIR/qca.framework) { exists($$QCA_LIBDIR/@QCA_LIB_NAME@.framework) {
QMAKE_CXXFLAGS += -F$$QCA_LIBDIR QMAKE_CXXFLAGS += -F$$QCA_LIBDIR
LIBS *= -F$$QCA_LIBDIR LIBS *= -F$$QCA_LIBDIR
INCLUDEPATH += $$QCA_LIBDIR/qca.framework/Headers INCLUDEPATH += $$QCA_LIBDIR/@QCA_LIB_NAME@.framework/Headers
LINKAGE = -framework qca LINKAGE = -framework @QCA_LIB_NAME@
} }
# else, link normally # else, link normally
isEmpty(LINKAGE) { isEmpty(LINKAGE) {
INCLUDEPATH += $$QCA_INCDIR/QtCrypto INCLUDEPATH += $$QCA_INCDIR/QtCrypto
LIBS += -L$$QCA_LIBDIR LIBS += -L$$QCA_LIBDIR
LINKAGE = -lqca LINKAGE = -l@QCA_LIB_NAME@
CONFIG(debug, debug|release) { CONFIG(debug, debug|release) {
windows:LINKAGE = -lqcad windows:LINKAGE = -l@QCA_LIB_NAME@d
mac:LINKAGE = -lqca_debug mac:LINKAGE = -l@QCA_LIB_NAME@_debug
} }
} }

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) if(QT6)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Qt5Core_EXECUTABLE_COMPILE_FLAGS}") find_package(Qt6 REQUIRED Network)
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Qt5Core_EXECUTABLE_COMPILE_FLAGS}")
find_package(Qt5 REQUIRED Network)
endif() endif()
add_subdirectory(aes-cmac) add_subdirectory(aes-cmac)
add_subdirectory(base64test) add_subdirectory(base64test)

View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

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

View File

@ -26,41 +26,40 @@
class QPixmap; class QPixmap;
namespace QCA namespace QCA {
{ class CertificateChain;
class CertificateChain; class KeyStoreEntry;
class KeyStoreEntry;
} }
class KeySelectDlg : public QDialog class KeySelectDlg : public QDialog
{ {
Q_OBJECT Q_OBJECT
public: public:
enum IconType enum IconType
{ {
IconCert, IconCert,
IconCrl, IconCrl,
IconKeyBundle, IconKeyBundle,
IconPgpPub, IconPgpPub,
IconPgpSec IconPgpSec
}; };
KeySelectDlg(QWidget *parent = 0); KeySelectDlg(QWidget *parent = 0);
~KeySelectDlg(); ~KeySelectDlg();
void setIcon(IconType type, const QPixmap &icon); void setIcon(IconType type, const QPixmap &icon);
signals: Q_SIGNALS:
void selected(const QCA::KeyStoreEntry &entry); void selected(const QCA::KeyStoreEntry &entry);
void viewCertificate(const QCA::CertificateChain &chain); void viewCertificate(const QCA::CertificateChain &chain);
protected slots: protected slots:
virtual void accept(); virtual void accept();
private: private:
class Private; class Private;
friend class Private; friend class Private;
Private *d; Private *d;
}; };
#endif #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 class Pkcs11ConfigDlg : public QDialog
{ {
public: public:
Pkcs11ConfigDlg(QWidget *parent = 0); Pkcs11ConfigDlg(QWidget *parent = 0);
Pkcs11ConfigDlg(const QString &providerName, const QVariantMap &config, QWidget *parent = 0); Pkcs11ConfigDlg(const QString &providerName, const QVariantMap &config, QWidget *parent = 0);
~Pkcs11ConfigDlg(); ~Pkcs11ConfigDlg();
static bool isSupported(); static bool isSupported();
protected slots: protected slots:
virtual void done(int r); virtual void done(int r);
private: private:
class Private; class Private;
Private *d; Private *d;
}; };
#endif #endif

View File

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

View File

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

View File

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

View File

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

View File

@ -24,7 +24,7 @@
#include <QCoreApplication> #include <QCoreApplication>
#include <stdio.h> #include <cstdio>
#ifdef QT_STATICPLUGIN #ifdef QT_STATICPLUGIN
#include "import_plugins.h" #include "import_plugins.h"
@ -32,47 +32,46 @@
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
// the Initializer object sets things up, and // the Initializer object sets things up, and
// also does cleanup when it goes out of scope // also does cleanup when it goes out of scope
QCA::Initializer init; QCA::Initializer init;
QCoreApplication app(argc, argv); QCoreApplication app(argc, argv);
// we use the first argument if provided, or // we use the first argument if provided, or
// use "hello" if no arguments // use "hello" if no arguments
QCA::SecureArray arg = (argc >= 2) ? argv[1] : "hello"; QCA::SecureArray arg = (argc >= 2) ? argv[1] : "hello";
// must always check that an algorithm is supported before using it // must always check that an algorithm is supported before using it
if( !QCA::isSupported("sha1") ) if (!QCA::isSupported("sha1"))
printf("SHA1 not supported!\n"); printf("SHA1 not supported!\n");
else { else {
// this shows the "all in one" approach // this shows the "all in one" approach
QString result = QCA::Hash("sha1").hashToString(arg); QString result = QCA::Hash(QStringLiteral("sha1")).hashToString(arg);
printf("sha1(\"%s\") = [%s]\n", arg.data(), qPrintable(result)); printf("sha1(\"%s\") = [%s]\n", arg.data(), qPrintable(result));
} }
// must always check that an algorithm is supported before using it // must always check that an algorithm is supported before using it
if( !QCA::isSupported("md5") ) if (!QCA::isSupported("md5"))
printf("MD5 not supported!\n"); printf("MD5 not supported!\n");
else { else {
// this shows the incremental approach. Naturally // this shows the incremental approach. Naturally
// for this simple job, we could use the "all in one" // for this simple job, we could use the "all in one"
// approach - this is an example, after all :-) // approach - this is an example, after all :-)
QCA::SecureArray part1(arg.toByteArray().left(3)); // three chars - "hel" QCA::SecureArray part1(arg.toByteArray().left(3)); // three chars - "hel"
QCA::SecureArray part2(arg.toByteArray().mid(3)); // the rest - "lo" QCA::SecureArray part2(arg.toByteArray().mid(3)); // the rest - "lo"
// create the required object. // create the required object.
QCA::Hash hashObject("md5"); QCA::Hash hashObject(QStringLiteral("md5"));
// we split it into two parts to show incremental update // we split it into two parts to show incremental update
hashObject.update(part1); hashObject.update(part1);
hashObject.update(part2); hashObject.update(part2);
// no more updates after calling final. // no more updates after calling final.
QCA::SecureArray resultArray = hashObject.final(); QCA::SecureArray resultArray = hashObject.final();
// convert the result into printable hexadecimal. // convert the result into printable hexadecimal.
QString result = QCA::arrayToHex(resultArray.toByteArray()); QString result = QCA::arrayToHex(resultArray.toByteArray());
printf("md5(\"%s\") = [%s]\n", arg.data(), qPrintable(result)); 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) int main(int argc, char **argv)
{ {
// the Initializer object sets things up, and // the Initializer object sets things up, and
// also does cleanup when it goes out of scope // also does cleanup when it goes out of scope
QCA::Initializer init; QCA::Initializer init;
QCoreApplication app(argc, argv); QCoreApplication app(argc, argv);
// we use the first argument as the data to encode / decode // we use the first argument as the data to encode / decode
// if an argument is provided. Use "hello" if no argument // if an argument is provided. Use "hello" if no argument
QByteArray arg; // empty array QByteArray arg; // empty array
arg.append((argc >= 2) ? argv[1] : "hello"); arg.append((argc >= 2) ? argv[1] : "hello");
// create our object, which does encoding by default // create our object, which does encoding by default
// QCA::Hex encoder(QCA::Encode); is equivalent // QCA::Hex encoder(QCA::Encode); is equivalent
QCA::Hex encoder; QCA::Hex encoder;
// You might prefer to use encoder.encode(); and have // You might prefer to use encoder.encode(); and have
// it return a QCA::SecureArray, depending on your needs // it return a QCA::SecureArray, depending on your needs
QString encoded = encoder.arrayToString(arg); QString encoded = encoder.arrayToString(arg);
std::cout << arg.data() << " in hex encoding is "; std::cout << arg.data() << " in hex encoding is ";
std::cout << encoded.toLatin1().data() << std::endl; std::cout << encoded.toLatin1().data() << std::endl;
// This time, we'll create an object to decode hexadecimal. // This time, we'll create an object to decode hexadecimal.
// We could also have reused the existing object, calling // We could also have reused the existing object, calling
// clear(); and setup(QCA::Decode); on it. // clear(); and setup(QCA::Decode); on it.
QCA::Hex decoder(QCA::Decode); QCA::Hex decoder(QCA::Decode);
// This time, we convert a QString into a QString // This time, we convert a QString into a QString
QString decoded = decoder.decodeString(encoded); QString decoded = decoder.decodeString(encoded);
std::cout << encoded.toLatin1().data() << " decoded from hex is "; std::cout << encoded.toLatin1().data() << " decoded from hex is ";
std::cout << decoded.toLatin1().data() << std::endl; std::cout << decoded.toLatin1().data() << std::endl;
return 0; return 0;
} }

View File

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

View File

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

View File

@ -26,7 +26,7 @@
#include <QDebug> #include <QDebug>
// needed for printf // needed for printf
#include<stdio.h> #include <cstdio>
#ifdef QT_STATICPLUGIN #ifdef QT_STATICPLUGIN
#include "import_plugins.h" #include "import_plugins.h"
@ -34,53 +34,52 @@
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
// the Initializer object sets things up, and // the Initializer object sets things up, and
// also does cleanup when it goes out of scope // also does cleanup when it goes out of scope
QCA::Initializer init; 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 // we use the first argument as the data to authenticate
// if an argument is provided. Use "hello" if no argument // if an argument is provided. Use "hello" if no argument
QByteArray arg = (argc >= 2) ? argv[1] : "hello"; QByteArray arg = (argc >= 2) ? argv[1] : "hello";
// we use the second argument as the key to authenticate // we use the second argument as the key to authenticate
// with, if two arguments are provided. Use "secret" as // with, if two arguments are provided. Use "secret" as
// the key if less than two arguments. // the key if less than two arguments.
QCA::SecureArray key((argc >= 3) ? argv[2] : "secret"); QCA::SecureArray key((argc >= 3) ? argv[2] : "secret");
// must always check that an algorithm is supported before using it // must always check that an algorithm is supported before using it
if( !QCA::isSupported("hmac(sha1)") ) { if (!QCA::isSupported("hmac(sha1)")) {
printf("HMAC(SHA1) not supported!\n"); printf("HMAC(SHA1) not supported!\n");
} else { } else {
// create the required object using HMAC with SHA-1, and an // create the required object using HMAC with SHA-1, and an
// empty key. // empty key.
QCA::MessageAuthenticationCode hmacObject( "hmac(sha1)", QCA::SecureArray() ); QCA::MessageAuthenticationCode hmacObject(QStringLiteral("hmac(sha1)"), QCA::SecureArray());
// create the key // create the key
QCA::SymmetricKey keyObject(key); QCA::SymmetricKey keyObject(key);
// set the HMAC object to use the key // set the HMAC object to use the key
hmacObject.setup(key); hmacObject.setup(key);
// that could also have been done in the // that could also have been done in the
// QCA::MessageAuthenticationCode constructor // QCA::MessageAuthenticationCode constructor
// we split it into two parts to show incremental update // we split it into two parts to show incremental update
QCA::SecureArray part1(arg.left(3)); // three chars - "hel" QCA::SecureArray part1(arg.left(3)); // three chars - "hel"
QCA::SecureArray part2(arg.mid(3)); // the rest - "lo" QCA::SecureArray part2(arg.mid(3)); // the rest - "lo"
hmacObject.update(part1); hmacObject.update(part1);
hmacObject.update(part2); hmacObject.update(part2);
// no more updates after calling final. // no more updates after calling final.
QCA::SecureArray resultArray = hmacObject.final(); QCA::SecureArray resultArray = hmacObject.final();
// convert the result into printable hexadecimal. // convert the result into printable hexadecimal.
QString result = QCA::arrayToHex(resultArray.toByteArray()); QString result = QCA::arrayToHex(resultArray.toByteArray());
printf("HMAC(SHA1) of \"%s\" with \"%s\" = [%s]\n", arg.data(), key.data(), result.toLatin1().data()); 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/) (http://www-128.ibm.com/developerworks/linux/library/l-md5crypt/)
*/ */
#include <QtCrypto>
#include <QCoreApplication> #include <QCoreApplication>
#include <QtCrypto>
#include <QtDebug> #include <QtDebug>
#include <stdio.h> #include <cstdio>
#ifdef QT_STATICPLUGIN #ifdef QT_STATICPLUGIN
#include "import_plugins.h" #include "import_plugins.h"
#endif #endif
QString to64 ( long v , int size ) QString to64(long v, int size)
{ {
// Character set of the encrypted password: A-Za-z0-9./ // Character set of the encrypted password: A-Za-z0-9./
QString itoa64 = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; QString itoa64 = QStringLiteral("./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz");
QString result; QString result;
while ( --size >= 0 ) while (--size >= 0) {
{ result.append(itoa64.at((int)(v & 0x3f)));
result.append ( itoa64.at ( ( int )( v & 0x3f ) ) );
v = v >> 6; v = v >> 6;
} }
return result; return result;
} }
int byte2unsigned(int byteValue)
int byte2unsigned ( int byteValue )
{ {
int integerToReturn; int integerToReturn;
integerToReturn = (int) byteValue & 0xff; integerToReturn = (int)byteValue & 0xff;
return integerToReturn; 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$"; QCA::SecureArray finalState, magic_string = "$1$";
// The md5crypt algorithm uses two separate hashes // The md5crypt algorithm uses two separate hashes
QCA::Hash hash1( "md5" ); QCA::Hash hash1(QStringLiteral("md5"));
QCA::Hash hash2( "md5" ); QCA::Hash hash2(QStringLiteral("md5"));
// MD5 Hash #1: pwd, magic string and salt // MD5 Hash #1: pwd, magic string and salt
hash1.update ( password ); hash1.update(password);
hash1.update ( magic_string ); hash1.update(magic_string);
hash1.update ( salt ); hash1.update(salt);
// MD5 Hash #2: password, salt, password // MD5 Hash #2: password, salt, password
hash2.update ( password ); hash2.update(password);
hash2.update ( salt ); hash2.update(salt);
hash2.update ( password ); hash2.update(password);
finalState = hash2.final(); finalState = hash2.final();
// Two sets of transformations based on the length of the password // 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) // 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 // Clear array bits
finalState.fill( 0 ); finalState.fill(0);
for ( int i = password.size() ; i != 0 ; i = i >> 1 ) for (int i = password.size(); i != 0; i = i >> 1) {
{ if ((i & 1) != 0) {
if ( ( i & 1 ) != 0 ) hash1.update(finalState.toByteArray().left(1));
{ } else {
hash1.update( finalState.toByteArray().left ( 1 ) ); hash1.update(password.toByteArray().left(1));
}
else
{
hash1.update( password.toByteArray().left ( 1 ) );
} }
} }
finalState = hash1.final(); finalState = hash1.final();
// Now build a 1000 entry dictionary... // Now build a 1000 entry dictionary...
for ( int i = 0 ; i < 1000 ; i++ ) for (int i = 0; i < 1000; i++) {
{
hash2.clear(); hash2.clear();
if ((i & 1) != 0) if ((i & 1) != 0) {
{ hash2.update(password);
hash2.update ( password ); } else {
} hash2.update(finalState.toByteArray().left(16));
else
{
hash2.update ( finalState.toByteArray().left( 16 ));
} }
if ((i % 3) != 0) if ((i % 3) != 0) {
{ hash2.update(salt);
hash2.update ( salt );
} }
if ((i % 7) != 0) if ((i % 7) != 0) {
{ hash2.update(password);
hash2.update ( password );
} }
if ((i & 1) != 0) if ((i & 1) != 0) {
{ hash2.update(finalState.toByteArray().left(16));
hash2.update ( finalState.toByteArray().left( 16 ) ); } else {
} hash2.update(password);
else
{
hash2.update ( password );
} }
finalState = hash2.final(); 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>$) // Salt is part of the encoded password ($1$<string>$)
QString encodedString; QString encodedString;
encodedString.append ( magic_string.toByteArray() ); encodedString.append(QString::fromLatin1(magic_string.toByteArray()));
encodedString.append ( salt.toByteArray() ); encodedString.append(QString::fromLatin1(salt.toByteArray()));
encodedString.append ( "$" ); encodedString.append(QStringLiteral("$"));
long l; long l;
l = ( byte2unsigned (finalState.toByteArray().at(0) ) << 16 | l = (byte2unsigned(finalState.toByteArray().at(0)) << 16 | (byte2unsigned(finalState.toByteArray().at(6))) << 8 |
( byte2unsigned (finalState.toByteArray().at(6)) ) << 8 | byte2unsigned(finalState.toByteArray().at(12)));
byte2unsigned (finalState.toByteArray().at(12)) ); encodedString.append(to64(l, 4));
encodedString.append ( to64 (l, 4) );
l = ( byte2unsigned (finalState.toByteArray().at(1)) << 16 | l = (byte2unsigned(finalState.toByteArray().at(1)) << 16 | (byte2unsigned(finalState.toByteArray().at(7))) << 8 |
( byte2unsigned (finalState.toByteArray().at(7))) << 8 | byte2unsigned(finalState.toByteArray().at(13)));
byte2unsigned (finalState.toByteArray().at(13)) ); encodedString.append(to64(l, 4));
encodedString.append ( to64 (l, 4) );
l = ( byte2unsigned (finalState.toByteArray().at(2)) << 16 | l = (byte2unsigned(finalState.toByteArray().at(2)) << 16 | (byte2unsigned(finalState.toByteArray().at(8))) << 8 |
( byte2unsigned (finalState.toByteArray().at(8))) << 8 | byte2unsigned(finalState.toByteArray().at(14)));
byte2unsigned (finalState.toByteArray().at(14)) ); encodedString.append(to64(l, 4));
encodedString.append ( to64 (l, 4) );
l = ( byte2unsigned (finalState.toByteArray().at(3)) << 16 | l = (byte2unsigned(finalState.toByteArray().at(3)) << 16 | (byte2unsigned(finalState.toByteArray().at(9))) << 8 |
( byte2unsigned (finalState.toByteArray().at(9))) << 8 | byte2unsigned(finalState.toByteArray().at(15)));
byte2unsigned (finalState.toByteArray().at(15)) ); encodedString.append(to64(l, 4));
encodedString.append ( to64 (l, 4) );
l = ( byte2unsigned (finalState.toByteArray().at(4)) << 16 | l = (byte2unsigned(finalState.toByteArray().at(4)) << 16 | (byte2unsigned(finalState.toByteArray().at(10))) << 8 |
( byte2unsigned (finalState.toByteArray().at(10))) << 8 | byte2unsigned(finalState.toByteArray().at(5)));
byte2unsigned (finalState.toByteArray().at(5)) ); encodedString.append(to64(l, 4));
encodedString.append ( to64 (l, 4) );
l = byte2unsigned (finalState.toByteArray().at(11)); l = byte2unsigned(finalState.toByteArray().at(11));
encodedString.append ( to64 (l, 2) ); encodedString.append(to64(l, 2));
return encodedString; return encodedString;
} }
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
// the Initializer object sets things up, and // the Initializer object sets things up, and
// also does cleanup when it goes out of scope // also does cleanup when it goes out of scope
QCA::Initializer init; QCA::Initializer init;
QCoreApplication app ( argc, argv ); QCoreApplication app(argc, argv);
QCA::SecureArray password, salt; QCA::SecureArray password, salt;
if ( argc < 3 ) if (argc < 3) {
{ printf("Usage: %s password salt (salt without $1$)\n", argv[0]);
printf ( "Usage: %s password salt (salt without $1$)\n" , argv[0] );
return 1; 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 // must always check that an algorithm is supported before using it
if( !QCA::isSupported( "md5" ) ) if (!QCA::isSupported("md5"))
printf ("MD5 hash not supported!\n"); printf("MD5 hash not supported!\n");
else else {
{ QString result = qca_md5crypt(password, salt);
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 // 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; return 0;
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,9 +1,8 @@
set(tlssocket_bin_moc_SRCS tlssocket.cpp) add_executable(tlssocket tlssocket.cpp main.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})
target_link_qca_libraries(tlssocket) 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) int main(int argc, char **argv)
{ {
QCA::Initializer init; QCA::Initializer init;
QCoreApplication qapp(argc, argv); QCoreApplication qapp(argc, argv);
TLSSocket socket; TLSSocket socket;
socket.connectToHostEncrypted("www.paypal.com", 443); socket.connectToHostEncrypted(QStringLiteral("www.paypal.com"), 443);
socket.write("GET / HTTP/1.0\r\n\r\n"); socket.write("GET / HTTP/1.0\r\n\r\n");
while(socket.waitForReadyRead()) while (socket.waitForReadyRead())
printf("%s", socket.readAll().data()); printf("%s", socket.readAll().constData());
return 0; return 0;
} }

View File

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

View File

@ -21,29 +21,30 @@
#ifndef TLSSOCKET_H #ifndef TLSSOCKET_H
#include <QtCrypto>
#include <QTcpSocket> #include <QTcpSocket>
#include <QtCrypto>
class TLSSocket : public QTcpSocket class TLSSocket : public QTcpSocket
{ {
Q_OBJECT
public: public:
TLSSocket(QObject *parent = 0); TLSSocket(QObject *parent = nullptr);
~TLSSocket(); ~TLSSocket() override;
void connectToHostEncrypted(const QString &host, quint16 port); void connectToHostEncrypted(const QString &host, quint16 port);
QCA::TLS *tls(); QCA::TLS *tls();
bool waitForReadyRead(int msecs = -1); bool waitForReadyRead(int msecs = -1) override;
protected: protected:
// from qiodevice // from qiodevice
virtual qint64 readData(char *data, qint64 maxlen); qint64 readData(char *data, qint64 maxlen) override;
virtual qint64 writeData(const char *data, qint64 len); qint64 writeData(const char *data, qint64 len) override;
private: private:
class Private; class Private;
friend class Private; friend class Private;
Private *d; Private *d;
}; };
#endif #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 #ifndef QCA_H
#define QCA_H #define QCA_H
#include "qca_core.h"
#include "qca_textfilter.h"
#include "qca_basic.h" #include "qca_basic.h"
#include "qca_publickey.h"
#include "qca_cert.h" #include "qca_cert.h"
#include "qca_core.h"
#include "qca_keystore.h" #include "qca_keystore.h"
#include "qca_publickey.h"
#include "qca_safetimer.h"
#include "qca_securelayer.h" #include "qca_securelayer.h"
#include "qca_securemessage.h" #include "qca_securemessage.h"
#include "qca_textfilter.h"
#include "qcaprovider.h" #include "qcaprovider.h"
#include "qpipe.h" #include "qpipe.h"
#include "qca_safetimer.h"
#endif #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 \file qca_export.h
Preprocessor magic to allow export of library symbols. Preprocessor magic to allow export of library symbols.
This is strictly internal. This is strictly internal.
@ -37,16 +37,16 @@
#include <QtGlobal> #include <QtGlobal>
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
# ifndef QCA_STATIC #ifndef QCA_STATIC
# ifdef QCA_MAKEDLL #ifdef QCA_MAKEDLL
# define QCA_EXPORT Q_DECL_EXPORT #define QCA_EXPORT Q_DECL_EXPORT
# else #else
# define QCA_EXPORT Q_DECL_IMPORT #define QCA_EXPORT Q_DECL_IMPORT
# endif #endif
# endif #endif
#endif #endif
#ifndef QCA_EXPORT #ifndef QCA_EXPORT
# define QCA_EXPORT #define QCA_EXPORT
#endif #endif
#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 class QCA_EXPORT SafeTimer : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
SafeTimer(QObject *parent = 0); SafeTimer(QObject *parent = nullptr);
~SafeTimer(); ~SafeTimer() override;
int interval() const; int interval() const;
bool isActive() const; bool isActive() const;
bool isSingleShot() const; bool isSingleShot() const;
void setInterval(int msec); void setInterval(int msec);
void setSingleShot(bool singleShot); void setSingleShot(bool singleShot);
int timerId() const; int timerId() const;
public slots: public Q_SLOTS:
void start(int msec); void start(int msec);
void start(); void start();
void stop(); void stop();
signals: Q_SIGNALS:
void timeout(); void timeout();
protected: protected:
bool event(QEvent *event); bool event(QEvent *event) override;
void timerEvent(QTimerEvent *event); void timerEvent(QTimerEvent *event) override;
private: private:
// Functions is used internally. Outer world mustn't have access them. // Functions is used internally. Outer world mustn't have access them.
void startTimer() {} void startTimer()
void killTimer(int) {} {
}
void killTimer(int)
{
}
class Private; class Private;
Private *d; 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 Superclass for text based filtering algorithms
This differs from Filter in that it has the concept 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. supports operations on QString arguments.
\ingroup UserAPI \ingroup UserAPI
@ -51,107 +51,107 @@ namespace QCA {
class QCA_EXPORT TextFilter : public Filter class QCA_EXPORT TextFilter : public Filter
{ {
public: public:
/** /**
Standard constructor Standard constructor
\param dir the Direction that this TextFilter \param dir the Direction that this TextFilter
should use. should use.
*/ */
TextFilter(Direction dir); TextFilter(Direction dir);
/** /**
Reset the TextFilter Reset the TextFilter
\param dir the Direction that this TextFilter \param dir the Direction that this TextFilter
should use. should use.
*/ */
void setup(Direction dir); void setup(Direction dir);
/** /**
The direction the TextFilter is set up to use The direction the TextFilter is set up to use
*/ */
Direction direction() const; Direction direction() const;
/** /**
Process an array in the "forward" direction, Process an array in the "forward" direction,
returning an array returning an array
This method runs in the forward direction, so This method runs in the forward direction, so
for something like a Base64 encoding, it takes for something like a Base64 encoding, it takes
the "native" array, and returns that array the "native" array, and returns that array
encoded in base64. encoded in base64.
\param a the array to encode \param a the array to encode
*/ */
MemoryRegion encode(const MemoryRegion &a); MemoryRegion encode(const MemoryRegion &a);
/** /**
Process an array in the "reverse" direction, Process an array in the "reverse" direction,
returning an array returning an array
This method runs in the reverse direction, so This method runs in the reverse direction, so
for something like a Base64 encoding, it takes for something like a Base64 encoding, it takes
a Base64 encoded array, and returns the "native" a Base64 encoded array, and returns the "native"
representation. representation.
\param a the array to decode \param a the array to decode
*/ */
MemoryRegion decode(const MemoryRegion &a); MemoryRegion decode(const MemoryRegion &a);
/** /**
Process an array in the "forward" direction, Process an array in the "forward" direction,
returning a QString returning a QString
This is equivalent to encode(), except This is equivalent to encode(), except
that it returns a QString, rather than a that it returns a QString, rather than a
byte array. byte array.
\param a the array to encode \param a the array to encode
*/ */
QString arrayToString(const MemoryRegion &a); QString arrayToString(const MemoryRegion &a);
/** /**
Process an string in the "reverse" direction, Process an string in the "reverse" direction,
returning a byte array returning a byte array
This is equivalent to decode(), except This is equivalent to decode(), except
that it takes a QString, rather than a that it takes a QString, rather than a
byte array. byte array.
\param s the array to decode \param s the array to decode
*/ */
MemoryRegion stringToArray(const QString &s); MemoryRegion stringToArray(const QString &s);
/** /**
Process a string in the "forward" direction, Process a string in the "forward" direction,
returning a string returning a string
This is equivalent to encode(), except This is equivalent to encode(), except
that it takes and returns a QString, rather than that it takes and returns a QString, rather than
byte arrays. byte arrays.
\param s the string to encode \param s the string to encode
*/ */
QString encodeString(const QString &s); QString encodeString(const QString &s);
/** /**
Process a string in the "reverse" direction, Process a string in the "reverse" direction,
returning a string returning a string
This is equivalent to decode(), except This is equivalent to decode(), except
that it takes and returns a QString, rather than that it takes and returns a QString, rather than
byte arrays. byte arrays.
\param s the string to decode \param s the string to decode
*/ */
QString decodeString(const QString &s); QString decodeString(const QString &s);
protected: protected:
/** /**
Internal state variable for the Direction Internal state variable for the Direction
that the filter operates in that the filter operates in
*/ */
Direction _dir; Direction _dir;
}; };
/** /**
@ -164,62 +164,62 @@ protected:
class QCA_EXPORT Hex : public TextFilter class QCA_EXPORT Hex : public TextFilter
{ {
public: 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 \note The direction can be changed using
the setup() call. the setup() call.
*/ */
Hex(Direction dir = Encode); Hex(Direction dir = Encode);
/** /**
Reset the internal state. Reset the internal state.
This is useful to reuse an existing Hex object This is useful to reuse an existing Hex object
*/ */
virtual void clear(); void clear() override;
/** /**
Process more data, returning the corresponding Process more data, returning the corresponding
encoded or decoded (depending on the Direction encoded or decoded (depending on the Direction
set in the constructor or setup() call) representation. set in the constructor or setup() call) representation.
If you find yourself with code that only calls If you find yourself with code that only calls
this method once, you might be better off using this method once, you might be better off using
encode() or decode(). Similarly, if the data is encode() or decode(). Similarly, if the data is
really a string, you might be better off using really a string, you might be better off using
arrayToString(), encodeString(), stringToArray() arrayToString(), encodeString(), stringToArray()
or decodeString(). or decodeString().
\param a the array containing data to process \param a the array containing data to process
*/ */
virtual MemoryRegion update(const MemoryRegion &a); MemoryRegion update(const MemoryRegion &a) override;
/** /**
Complete the algorithm Complete the algorithm
\return any remaining output. Because of the way \return any remaining output. Because of the way
hexadecimal encoding works, this will return a hexadecimal encoding works, this will return a
zero length array - any output will have been returned zero length array - any output will have been returned
from the update() call. from the update() call.
*/ */
virtual MemoryRegion final(); MemoryRegion final() override;
/** /**
Test if an update() or final() call succeeded. Test if an update() or final() call succeeded.
\return true if the previous call succeeded \return true if the previous call succeeded
*/ */
virtual bool ok() const; bool ok() const override;
private: private:
Q_DISABLE_COPY(Hex) Q_DISABLE_COPY(Hex)
uchar val; uchar val;
bool partial; bool partial;
bool _ok; bool _ok;
}; };
/** /**
@ -232,94 +232,94 @@ private:
class QCA_EXPORT Base64 : public TextFilter class QCA_EXPORT Base64 : public TextFilter
{ {
public: 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 \note The direction can be changed using
the setup() call. the setup() call.
*/ */
Base64(Direction dir = Encode); Base64(Direction dir = Encode);
/** /**
Returns true if line breaks are enabled Returns true if line breaks are enabled
*/ */
bool lineBreaksEnabled() const; bool lineBreaksEnabled() const;
/** /**
Returns the line break column Returns the line break column
*/ */
int lineBreaksColumn() const; int lineBreaksColumn() const;
/** /**
Sets line break mode. If enabled, linebreaks will be Sets line break mode. If enabled, linebreaks will be
added to encoded output or accepted in encoded input. added to encoded output or accepted in encoded input.
If disabled, linebreaks in encoded input will cause If disabled, linebreaks in encoded input will cause
a failure to decode. The default is disabled. a failure to decode. The default is disabled.
\param b whether to enable line breaks (true) or disable line breaks (false) \param b whether to enable line breaks (true) or disable line breaks (false)
*/ */
void setLineBreaksEnabled(bool b); void setLineBreaksEnabled(bool b);
/** /**
Sets the column that linebreaks should be inserted at Sets the column that linebreaks should be inserted at
when encoding. when encoding.
\param column the column number that line breaks should be inserted at. \param column the column number that line breaks should be inserted at.
*/ */
void setLineBreaksColumn(int column); void setLineBreaksColumn(int column);
/** /**
Reset the internal state. This is useful to Reset the internal state. This is useful to
reuse an existing Base64 object reuse an existing Base64 object
*/ */
virtual void clear(); void clear() override;
/** /**
Process more data, returning the corresponding Process more data, returning the corresponding
encoded or decoded (depending on the Direction encoded or decoded (depending on the Direction
set in the constructor or setup() call) representation. set in the constructor or setup() call) representation.
If you find yourself with code that only calls If you find yourself with code that only calls
this method once, you might be better off using this method once, you might be better off using
encode() or decode(). Similarly, if the data is encode() or decode(). Similarly, if the data is
really a string, you might be better off using really a string, you might be better off using
arrayToString(), encodeString(), stringToArray() arrayToString(), encodeString(), stringToArray()
or decodeString(). or decodeString().
\param a the array containing data to process \param a the array containing data to process
*/ */
virtual MemoryRegion update(const MemoryRegion &a); MemoryRegion update(const MemoryRegion &a) override;
/** /**
Complete the algorithm Complete the algorithm
\return any remaining output. Because of the way \return any remaining output. Because of the way
Base64 encoding works, you will get either an Base64 encoding works, you will get either an
empty array, or an array containing one or two empty array, or an array containing one or two
"=" (equals, 0x3D) characters. "=" (equals, 0x3D) characters.
*/ */
virtual MemoryRegion final(); MemoryRegion final() override;
/** /**
Test if an update() or final() call succeeded. Test if an update() or final() call succeeded.
\return true if the previous call succeeded \return true if the previous call succeeded
*/ */
virtual bool ok() const; bool ok() const override;
private: private:
Q_DISABLE_COPY(Base64) Q_DISABLE_COPY(Base64)
QByteArray partial; QByteArray partial;
bool _ok; bool _ok;
int col; int col;
bool _lb_enabled; bool _lb_enabled;
int _lb_column; int _lb_column;
class Private; class Private;
Private *d; 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 DOXYGEN_SHOULD_SKIP_THIS
#ifndef QPIPE_NO_SECURE #ifndef QPIPE_NO_SECURE
# define QPIPE_SECURE #define QPIPE_SECURE
#endif #endif
#ifdef QPIPE_SECURE #ifdef QPIPE_SECURE
# include "QtCrypto" #include "QtCrypto"
#else #else
# define QCA_EXPORT #define QCA_EXPORT
#endif #endif
// defs adapted qprocess_p.h // defs adapted qprocess_p.h
@ -61,7 +61,6 @@ typedef int Q_PIPE_ID;
namespace QCA { namespace QCA {
/** /**
\class QPipeDevice qpipe.h QtCrypto \class QPipeDevice qpipe.h QtCrypto
@ -74,136 +73,136 @@ namespace QCA {
*/ */
class QCA_EXPORT QPipeDevice : public QObject class QCA_EXPORT QPipeDevice : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
/** /**
The type of device The type of device
*/ */
enum Type enum Type
{ {
Read, ///< The pipe end can be read from Read, ///< The pipe end can be read from
Write ///< The pipe end can be written to Write ///< The pipe end can be written to
}; };
/** /**
Standard constructor Standard constructor
\param parent the parent object to this object \param parent the parent object to this object
*/ */
QPipeDevice(QObject *parent = 0); QPipeDevice(QObject *parent = nullptr);
~QPipeDevice(); ~QPipeDevice() override;
/** /**
The Type of the pipe device (that is, read or write) The Type of the pipe device (that is, read or write)
*/ */
Type type() const; Type type() const;
/** /**
Test whether this object corresponds to a valid pipe Test whether this object corresponds to a valid pipe
*/ */
bool isValid() const; 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 \sa idAsInt
*/ */
Q_PIPE_ID id() const; 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(). \sa id().
*/ */
int idAsInt() const; 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 id the identification of the pipe end to take over.
\param t the type of pipe end (read or write). \param t the type of pipe end (read or write).
*/ */
void take(Q_PIPE_ID id, Type t); void take(Q_PIPE_ID id, Type t);
/** /**
Enable the pipe for reading or writing (depending on Type) Enable the pipe for reading or writing (depending on Type)
*/ */
void enable(); void enable();
/** /**
Close the pipe end. Close the pipe end.
*/ */
void close(); void close();
/** /**
Release the pipe end, but do not close it. Release the pipe end, but do not close it.
*/ */
void release(); 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) \param enabled whether the pipe is inheritable (true) or not (false)
*/ */
bool setInheritable(bool enabled); bool setInheritable(bool enabled);
/** /**
Obtain the number of bytes available to be read. Obtain the number of bytes available to be read.
*/ */
int bytesAvailable() const; 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 data where to put the data that has been read
\param maxsize the maximum number of bytes to be 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. \return the actual number of bytes read, 0 on end-of-file, or -1 on error.
*/ */
int read(char *data, int maxsize); 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 data the source of the data to be written
\param size the number of bytes in 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. \return the number of bytes written, or -1 on error.
*/ */
int write(const char *data, int size); 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 \param written if not null, this will be set to the number of
bytes written in the last operation. bytes written in the last operation.
\return 0 on success (all data written), or -1 on error \return 0 on success (all data written), or -1 on error
*/ */
int writeResult(int *written) const; int writeResult(int *written) const;
Q_SIGNALS: Q_SIGNALS:
/** /**
Emitted when the pipe end can be read from or written to (depending on its Type). Emitted when the pipe end can be read from or written to (depending on its Type).
*/ */
void notify(); void notify();
private: private:
Q_DISABLE_COPY(QPipeDevice) Q_DISABLE_COPY(QPipeDevice)
class Private; class Private;
friend class Private; friend class Private;
Private *d; Private *d;
}; };
/** /**
@ -217,248 +216,247 @@ private:
*/ */
class QCA_EXPORT QPipeEnd : public QObject class QCA_EXPORT QPipeEnd : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
/**
The type of error
*/
enum Error
{
ErrorEOF, ///< End of file error
ErrorBroken ///< Broken pipe error
};
/** /**
The type of error Standard constructor
*/
enum Error
{
ErrorEOF, ///< End of file error
ErrorBroken ///< Broken pipe error
};
/** \param parent the parent object for this object
Standard constructor */
QPipeEnd(QObject *parent = nullptr);
\param parent the parent object for this object ~QPipeEnd() override;
*/
QPipeEnd(QObject *parent = 0);
~QPipeEnd(); /**
Reset the pipe end to an inactive state
*/
void reset();
/** /**
Reset the pipe end to an inactive state The type of pipe end (either read or write)
*/ */
void reset(); QPipeDevice::Type type() const;
/** /**
The type of pipe end (either read or write) Determine whether the pipe end is valid.
*/
QPipeDevice::Type type() const;
/** \note This does not mean the pipe is ready to be used - you
Determine whether the pipe end is valid. 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 Pipe identification
*/ */
bool isValid() const; Q_PIPE_ID id() const;
/** /**
Pipe identification Pipe identification
*/ */
Q_PIPE_ID id() const; int idAsInt() const;
/** /**
Pipe identification Take over an existing pipe handle
*/
int idAsInt() const;
/** \param id the pipe handle
Take over an existing pipe handle \param t the type of the pipe (read or write)
*/
\param id the pipe handle void take(Q_PIPE_ID id, QPipeDevice::Type t);
\param t the type of the pipe (read or write)
*/
void take(Q_PIPE_ID id, QPipeDevice::Type t);
#ifdef QPIPE_SECURE #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 Enabling this may reduce performance, and it should only be used if
sensitive data is being transmitted (such as a passphrase). sensitive data is being transmitted (such as a passphrase).
\param secure whether the pipe uses secure memory (true) or not (false). \param secure whether the pipe uses secure memory (true) or not (false).
*/ */
void setSecurityEnabled(bool secure); void setSecurityEnabled(bool secure);
#endif #endif
/** /**
Enable the endpoint for the pipe Enable the endpoint for the pipe
When an endpoint is created, it is not When an endpoint is created, it is not
able to be used until it is enabled. able to be used until it is enabled.
*/ */
void enable(); void enable();
/** /**
Close the end of the pipe Close the end of the pipe
\sa closed() \sa closed()
*/ */
void close(); 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 Use this before destructing QPipeEnd, if you don't want the pipe
to automatically close. to automatically close.
*/ */
void release(); 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 Returns true if inheritability was successfully changed, otherwise
false. false.
\param enabled whether the pipe is inheritable (true) or not (false). \param enabled whether the pipe is inheritable (true) or not (false).
*/ */
bool setInheritable(bool enabled); bool setInheritable(bool enabled);
/** /**
Clear the contents of the pipe, and invalidate the pipe Clear the contents of the pipe, and invalidate the pipe
*/ */
void finalize(); void finalize();
/** /**
Clear the contents of the pipe, and release the pipe Clear the contents of the pipe, and release the pipe
*/ */
void finalizeAndRelease(); 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 \sa readyRead() for a signal that can be used to determine
when there are bytes available to read. when there are bytes available to read.
*/ */
int bytesAvailable() const; 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 \sa bytesWritten() for a signal that can be used to determine
when bytes have been written when bytes have been written
*/ */
int bytesToWrite() const; 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 \param bytes the number of bytes to read (-1 for all
content). content).
*/ */
QByteArray read(int bytes = -1); 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 \param a the array to write to the pipe
*/ */
void write(const QByteArray &a); void write(const QByteArray &a);
#ifdef QPIPE_SECURE #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 \param bytes the number of bytes to read (-1 for all
content). content).
*/ */
SecureArray readSecure(int bytes = -1); 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 \param a the array to write to the pipe
*/ */
void writeSecure(const SecureArray &a); void writeSecure(const SecureArray &a);
#endif #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 If the pipe is using secure memory, you should use
takeBytesToWriteSecure(). takeBytesToWriteSecure().
*/ */
QByteArray takeBytesToWrite(); QByteArray takeBytesToWrite();
#ifdef QPIPE_SECURE #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 If the pipe is using insecure memory, you should use
takeBytesToWrite(). takeBytesToWrite().
*/ */
SecureArray takeBytesToWriteSecure(); SecureArray takeBytesToWriteSecure();
#endif #endif
Q_SIGNALS: Q_SIGNALS:
/** /**
Emitted when there are bytes available to be read Emitted when there are bytes available to be read
from the read end of the pipe. from the read end of the pipe.
\sa bytesAvailable() \sa bytesAvailable()
*/ */
void readyRead(); void readyRead();
/** /**
Emitted when bytes have been written to the Emitted when bytes have been written to the
write end of the pipe. write end of the pipe.
\param bytes the number of bytes written \param bytes the number of bytes written
*/ */
void bytesWritten(int bytes); void bytesWritten(int bytes);
/** /**
Emitted when this end of the pipe is closed as a result of calling Emitted when this end of the pipe is closed as a result of calling
close() close()
If this is the write end of the pipe and there is data still 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 pending to write, this signal will be emitted once all of the data
has been written. has been written.
To be notified if the other end of the pipe has been closed, see To be notified if the other end of the pipe has been closed, see
error(). error().
*/ */
void closed(); void closed();
/** /**
Emitted when the pipe encounters an error trying to read or write, Emitted when the pipe encounters an error trying to read or write,
or if the other end of the pipe has been closed or if the other end of the pipe has been closed
\param e the reason for error \param e the reason for error
*/ */
void error(QCA::QPipeEnd::Error e); void error(QCA::QPipeEnd::Error e);
private: private:
Q_DISABLE_COPY(QPipeEnd) Q_DISABLE_COPY(QPipeEnd)
class Private; class Private;
friend class Private; friend class Private;
Private *d; Private *d;
}; };
/** /**
@ -480,53 +478,59 @@ private:
class QCA_EXPORT QPipe class QCA_EXPORT QPipe
{ {
public: 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 \param parent the parent object for this object
*/ */
QPipe(QObject *parent = 0); QPipe(QObject *parent = nullptr);
~QPipe(); ~QPipe();
/** /**
Reset the pipe. Reset the pipe.
At this point, the readEnd() and writeEnd() calls At this point, the readEnd() and writeEnd() calls
will no longer be valid. will no longer be valid.
*/ */
void reset(); void reset();
#ifdef QPIPE_SECURE #ifdef QPIPE_SECURE
/** /**
Create the pipe Create the pipe
\param secure whether to use secure memory (true) or not (false) \param secure whether to use secure memory (true) or not (false)
*/ */
bool create(bool secure = false); bool create(bool secure = false);
#else #else
/** /**
Create the pipe Create the pipe
*/ */
bool create(); bool create();
#endif #endif
/** /**
The read end of the pipe. The read end of the pipe.
*/ */
QPipeEnd & readEnd() { return i; } QPipeEnd &readEnd()
{
return i;
}
/** /**
The write end of the pipe. The write end of the pipe.
*/ */
QPipeEnd & writeEnd() { return o; } QPipeEnd &writeEnd()
{
return o;
}
private: 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") set(WITH_${PLUGIN}_PLUGIN "yes")
elseif("${BUILD_PLUGINS}" STREQUAL "auto") elseif("${BUILD_PLUGINS}" STREQUAL "auto")
set(WITH_${PLUGIN}_PLUGIN "auto") set(WITH_${PLUGIN}_PLUGIN "auto")
else("${BUILD_PLUGINS}" STREQUAL "all") else()
set(WITH_${PLUGIN}_PLUGIN "no") set(WITH_${PLUGIN}_PLUGIN "no")
endif("${BUILD_PLUGINS}" STREQUAL "all") endif()
elseif(NOT WITH_${PLUGIN}_PLUGIN) elseif(NOT WITH_${PLUGIN}_PLUGIN)
set(WITH_${PLUGIN}_PLUGIN "no") set(WITH_${PLUGIN}_PLUGIN "no")
elseif("${WITH_${PLUGIN}_PLUGIN}" STREQUAL "auto") elseif("${WITH_${PLUGIN}_PLUGIN}" STREQUAL "auto")
set(WITH_${PLUGIN}_PLUGIN "auto") set(WITH_${PLUGIN}_PLUGIN "auto")
else("${WITH_${PLUGIN}_PLUGIN}" STREQUAL "") else()
set(WITH_${PLUGIN}_PLUGIN "yes") set(WITH_${PLUGIN}_PLUGIN "yes")
endif("${WITH_${PLUGIN}_PLUGIN}" STREQUAL "") endif()
# Build plugin if yes or auto # Build plugin if yes or auto
if(WITH_${PLUGIN}_PLUGIN) if(WITH_${PLUGIN}_PLUGIN)
add_subdirectory("qca-${PLUGIN}") add_subdirectory("qca-${PLUGIN}")
else(WITH_${PLUGIN}_PLUGIN) else()
disable_plugin(${PLUGIN}) disable_plugin(${PLUGIN})
endif(WITH_${PLUGIN}_PLUGIN) endif()
endforeach(PLUGIN IN LISTS PLUGINS) endforeach(PLUGIN IN LISTS PLUGINS)
else(NOT_PLUGIN_LIST) else()
# BUILD_PLUGINS has list plugins to builds # BUILD_PLUGINS has list plugins to builds
foreach(PLUGIN IN LISTS PLUGINS) foreach(PLUGIN IN LISTS PLUGINS)
list(FIND BUILD_PLUGINS "${PLUGIN}" PLUGIN_INDEX) list(FIND BUILD_PLUGINS "${PLUGIN}" PLUGIN_INDEX)
if(PLUGIN_INDEX GREATER -1) if(PLUGIN_INDEX GREATER -1)
set(WITH_${PLUGIN}_PLUGIN "yes") set(WITH_${PLUGIN}_PLUGIN "yes")
add_subdirectory("qca-${PLUGIN}") add_subdirectory("qca-${PLUGIN}")
else(PLUGIN_INDEX GREATER -1) else()
disable_plugin(${PLUGIN}) disable_plugin(${PLUGIN})
endif(PLUGIN_INDEX GREATER -1) endif()
endforeach(PLUGIN IN LISTS PLUGINS) endforeach(PLUGIN IN LISTS PLUGINS)
endif(NOT_PLUGIN_LIST) endif()
message("") message("")
message("Plugins:") message("Plugins:")

View File

@ -1,22 +1,25 @@
find_package(PkgConfig REQUIRED)
if(WITH_botan_PLUGIN STREQUAL "yes") if(WITH_botan_PLUGIN STREQUAL "yes")
find_package(Botan REQUIRED) pkg_check_modules(BOTAN REQUIRED IMPORTED_TARGET botan-2)
else(WITH_botan_PLUGIN STREQUAL "yes") else()
find_package(Botan) pkg_check_modules(BOTAN IMPORTED_TARGET botan-2)
endif(WITH_botan_PLUGIN STREQUAL "yes") endif()
if(BOTAN_FOUND) if(BOTAN_FOUND)
enable_plugin("botan") enable_plugin("botan")
set(QCA_BOTAN_SOURCES qca-botan.cpp) 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}) add_library(qca-botan ${PLUGIN_TYPE} ${QCA_BOTAN_SOURCES})
if(APPLE AND ${PLUGIN_TYPE} STREQUAL "MODULE") if(APPLE AND ${PLUGIN_TYPE} STREQUAL "MODULE")
set_property(TARGET qca-botan PROPERTY SUFFIX ".dylib") set_property(TARGET qca-botan PROPERTY SUFFIX ".dylib")
endif() 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) if(NOT DEVELOPER_MODE)
install(TARGETS qca-botan install(TARGETS qca-botan
@ -27,6 +30,6 @@ if(BOTAN_FOUND)
install_pdb(qca-botan ${QCA_CRYPTO_INSTALL_DIR}) install_pdb(qca-botan ${QCA_CRYPTO_INSTALL_DIR})
endif() endif()
else(BOTAN_FOUND) else()
disable_plugin("botan") 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") if(WITH_cyrus-sasl_PLUGIN STREQUAL "yes")
find_package(Sasl2 REQUIRED) find_package(Sasl2 REQUIRED)
else(WITH_cyrus-sasl_PLUGIN STREQUAL "yes") else()
find_package(Sasl2) find_package(Sasl2)
endif(WITH_cyrus-sasl_PLUGIN STREQUAL "yes") endif()
if(SASL2_FOUND) if(SASL2_FOUND)
enable_plugin("cyrus-sasl") enable_plugin("cyrus-sasl")
set(QCA_SASL_SOURCES qca-cyrus-sasl.cpp) set(QCA_SASL_SOURCES qca-cyrus-sasl.cpp)
include_directories( ${SASL2_INCLUDE_DIR} ) include_directories( ${SASL2_INCLUDE_DIR} )
my_automoc( QCA_SASL_SOURCES )
add_library(qca-cyrus-sasl ${PLUGIN_TYPE} ${QCA_SASL_SOURCES}) add_library(qca-cyrus-sasl ${PLUGIN_TYPE} ${QCA_SASL_SOURCES})
if(APPLE AND ${PLUGIN_TYPE} STREQUAL "MODULE") if(APPLE AND ${PLUGIN_TYPE} STREQUAL "MODULE")
set_property(TARGET qca-cyrus-sasl PROPERTY SUFFIX ".dylib") set_property(TARGET qca-cyrus-sasl PROPERTY SUFFIX ".dylib")
endif() 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) if(NOT DEVELOPER_MODE)
install(TARGETS qca-cyrus-sasl install(TARGETS qca-cyrus-sasl
@ -26,6 +29,6 @@ if(SASL2_FOUND)
install_pdb(qca-cyrus-sasl ${QCA_CRYPTO_INSTALL_DIR}) install_pdb(qca-cyrus-sasl ${QCA_CRYPTO_INSTALL_DIR})
endif() endif()
else(SASL2_FOUND) else()
disable_plugin("cyrus-sasl") 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") if(WITH_gcrypt_PLUGIN STREQUAL "yes")
find_package(LibGcrypt REQUIRED) find_package(LibGcrypt REQUIRED)
else(WITH_gcrypt_PLUGIN STREQUAL "yes") else()
find_package(LibGcrypt) find_package(LibGcrypt)
endif(WITH_gcrypt_PLUGIN STREQUAL "yes") endif()
if(LIBGCRYPT_FOUND) if(LIBGCRYPT_FOUND)
include(CheckTypeSize) include(CheckTypeSize)
@ -19,14 +19,17 @@ if(LIBGCRYPT_FOUND)
set(QCA_GCRYPT_SOURCES qca-gcrypt.cpp) set(QCA_GCRYPT_SOURCES qca-gcrypt.cpp)
add_definitions(${LIBGCRYPT_CFLAGS}) add_definitions(${LIBGCRYPT_CFLAGS})
my_automoc(QCA_GCRYPT_SOURCES)
add_library(qca-gcrypt ${PLUGIN_TYPE} ${QCA_GCRYPT_SOURCES}) add_library(qca-gcrypt ${PLUGIN_TYPE} ${QCA_GCRYPT_SOURCES})
if(APPLE AND ${PLUGIN_TYPE} STREQUAL "MODULE") if(APPLE AND ${PLUGIN_TYPE} STREQUAL "MODULE")
set_property(TARGET qca-gcrypt PROPERTY SUFFIX ".dylib") set_property(TARGET qca-gcrypt PROPERTY SUFFIX ".dylib")
endif() 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) if(NOT DEVELOPER_MODE)
install(TARGETS qca-gcrypt install(TARGETS qca-gcrypt
@ -36,10 +39,10 @@ if(LIBGCRYPT_FOUND)
install_pdb(qca-gcrypt ${QCA_CRYPTO_INSTALL_DIR}) install_pdb(qca-gcrypt ${QCA_CRYPTO_INSTALL_DIR})
endif() endif()
else(HAVE_GCRY_ERROR_T) else()
message(STATUS "libgcrypt seems to be too old") message(STATUS "libgcrypt seems to be too old")
disable_plugin("gcrypt") disable_plugin("gcrypt")
endif(HAVE_GCRY_ERROR_T) endif()
else(LIBGCRYPT_FOUND) else()
disable_plugin("gcrypt") 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 * Output: DK derived key, a dkLen-octet string
*/ */
gcry_error_t static gcry_error_t gcry_pbkdf2(int PRF,
gcry_pbkdf2 (int PRF, const char *P, size_t Plen, const char *S, const char * P,
size_t Slen, unsigned int c, unsigned int dkLen, char *DK) size_t Plen,
const char * S,
size_t Slen,
unsigned int c,
unsigned int dkLen,
char * DK)
{ {
gcry_md_hd_t prf; gcry_md_hd_t prf;
gcry_error_t rc; gcry_error_t rc;
char *U; char * U;
unsigned int u; unsigned int u;
unsigned int hLen; unsigned int hLen;
unsigned int l; unsigned int l;
unsigned int r; unsigned int r;
unsigned char *p; unsigned char *p;
unsigned int i; unsigned int i;
unsigned int k; unsigned int k;
hLen = gcry_md_get_algo_dlen (PRF); hLen = gcry_md_get_algo_dlen(PRF);
if (hLen == 0) if (hLen == 0)
return GPG_ERR_UNSUPPORTED_ALGORITHM; return GPG_ERR_UNSUPPORTED_ALGORITHM;
if (c == 0) if (c == 0)
return GPG_ERR_INV_ARG; return GPG_ERR_INV_ARG;
if (dkLen == 0) if (dkLen == 0)
return GPG_ERR_TOO_SHORT; return GPG_ERR_TOO_SHORT;
/* /*
* *
* Steps: * Steps:
* *
* 1. If dkLen > (2^32 - 1) * hLen, output "derived key too long" and * 1. If dkLen > (2^32 - 1) * hLen, output "derived key too long" and
* stop. * stop.
*/ */
if (dkLen > 4294967295U) if (dkLen > 4294967295U)
return GPG_ERR_TOO_LARGE; return GPG_ERR_TOO_LARGE;
/* /*
* 2. Let l be the number of hLen-octet blocks in the derived key, * 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 * rounding up, and let r be the number of octets in the last
* block: * block:
* *
* l = CEIL (dkLen / hLen) , * l = CEIL (dkLen / hLen) ,
* r = dkLen - (l - 1) * hLen . * r = dkLen - (l - 1) * hLen .
* *
* Here, CEIL (x) is the "ceiling" function, i.e. the smallest * Here, CEIL (x) is the "ceiling" function, i.e. the smallest
* integer greater than, or equal to, x. * integer greater than, or equal to, x.
*/ */
l = dkLen / hLen; l = dkLen / hLen;
if (dkLen % hLen) if (dkLen % hLen)
l++; l++;
r = dkLen - (l - 1) * hLen; r = dkLen - (l - 1) * hLen;
/* /*
* 3. For each block of the derived key apply the function F defined * 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 * below to the password P, the salt S, the iteration count c, and
* the block index to compute the block: * the block index to compute the block:
* *
* T_1 = F (P, S, c, 1) , * T_1 = F (P, S, c, 1) ,
* T_2 = F (P, S, c, 2) , * T_2 = F (P, S, c, 2) ,
* ... * ...
* T_l = F (P, S, c, l) , * T_l = F (P, S, c, l) ,
* *
* where the function F is defined as the exclusive-or sum of the * where the function F is defined as the exclusive-or sum of the
* first c iterates of the underlying pseudorandom function PRF * first c iterates of the underlying pseudorandom function PRF
* applied to the password P and the concatenation of the salt S * applied to the password P and the concatenation of the salt S
* and the block index i: * and the block index i:
* *
* F (P, S, c, i) = U_1 \xor U_2 \xor ... \xor U_c * F (P, S, c, i) = U_1 \xor U_2 \xor ... \xor U_c
* *
* where * where
* *
* U_1 = PRF (P, S || INT (i)) , * U_1 = PRF (P, S || INT (i)) ,
* U_2 = PRF (P, U_1) , * U_2 = PRF (P, U_1) ,
* ... * ...
* U_c = PRF (P, U_{c-1}) . * U_c = PRF (P, U_{c-1}) .
* *
* Here, INT (i) is a four-octet encoding of the integer i, most * Here, INT (i) is a four-octet encoding of the integer i, most
* significant octet first. * significant octet first.
* *
* 4. Concatenate the blocks and extract the first dkLen octets to * 4. Concatenate the blocks and extract the first dkLen octets to
* produce a derived key DK: * produce a derived key DK:
* *
* DK = T_1 || T_2 || ... || T_l<0..r-1> * DK = T_1 || T_2 || ... || T_l<0..r-1>
* *
* 5. Output the derived key DK. * 5. Output the derived key DK.
* *
* Note. The construction of the function F follows a "belt-and- * Note. The construction of the function F follows a "belt-and-
* suspenders" approach. The iterates U_i are computed recursively to * suspenders" approach. The iterates U_i are computed recursively to
* remove a degree of parallelism from an opponent; they are exclusive- * remove a degree of parallelism from an opponent; they are exclusive-
* ored together to reduce concerns about the recursion degenerating * ored together to reduce concerns about the recursion degenerating
* into a small set of values. * into a small set of values.
* *
*/ */
rc = gcry_md_open (&prf, PRF, GCRY_MD_FLAG_HMAC | GCRY_MD_FLAG_SECURE); rc = gcry_md_open(&prf, PRF, GCRY_MD_FLAG_HMAC | GCRY_MD_FLAG_SECURE);
if (rc != GPG_ERR_NO_ERROR) 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; 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") enable_plugin("gnupg")
set(QCA_GNUPG_MOC_SOURCES set(QCA_GNUPG_SOURCES
qca-gnupg.cpp qca-gnupg.cpp
)
set(QCA_GNUPG_NONMOC_SOURCES
gpgop.cpp gpgop.cpp
utils.cpp utils.cpp
gpgproc/sprocess.cpp gpgproc/sprocess.cpp
@ -21,30 +18,39 @@ set(QCA_GNUPG_NONMOC_SOURCES
gpgproc/gpgproc.cpp 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) add_library(qca-gnupg ${PLUGIN_TYPE} ${QCA_GNUPG_SOURCES} ${EXTRA_GNUPG_SOURCES} ${QCA_GNUPG_HEADERS})
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})
if(APPLE AND ${PLUGIN_TYPE} STREQUAL "MODULE") if(APPLE AND ${PLUGIN_TYPE} STREQUAL "MODULE")
set_property(TARGET qca-gnupg PROPERTY SUFFIX ".dylib") set_property(TARGET qca-gnupg PROPERTY SUFFIX ".dylib")
endif() endif()
include_directories(gpgproc) 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) if (WIN32)
target_link_libraries(qca-gnupg advapi32) target_link_libraries(qca-gnupg advapi32)
endif (WIN32) endif()
if(NOT DEVELOPER_MODE) if(NOT DEVELOPER_MODE)
install(TARGETS qca-gnupg DESTINATION install(TARGETS qca-gnupg DESTINATION

File diff suppressed because it is too large Load Diff

View File

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

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