mirror of
https://github.com/QuasarApp/qca.git
synced 2025-04-26 11:34:32 +00:00
Compare commits
178 Commits
Author | SHA1 | Date | |
---|---|---|---|
45f2312979 | |||
a602142dcb | |||
5b49c00168 | |||
|
e9fd31b4a1 | ||
|
7ead054437 | ||
|
b2e54520a3 | ||
|
5cc26f77f0 | ||
|
2c3992f075 | ||
|
0c3db8a062 | ||
|
974f8ec8d0 | ||
|
040d7d6348 | ||
|
d8f1e6cb9c | ||
|
9443ba76ba | ||
|
effbe387a0 | ||
|
e6a15466ae | ||
|
35366fea78 | ||
|
3e90e13d5e | ||
|
91ff0aa0db | ||
|
564e906dd1 | ||
|
d3d16fcc17 | ||
|
797b430540 | ||
|
ecdd0538dd | ||
|
aa26b43be2 | ||
|
bc94cc08e1 | ||
|
2d7e7e8242 | ||
|
32275f1a74 | ||
|
1bcde93efc | ||
|
e9e0f2085d | ||
|
bd31ef1587 | ||
|
7174e6ed70 | ||
|
0684db8255 | ||
|
dfb96ac596 | ||
|
f62a8ee8f7 | ||
|
04dbe5ca7d | ||
|
db8ff052a9 | ||
|
f88abb0697 | ||
|
0fd3c4cb26 | ||
|
0d174fea58 | ||
|
fb926ae7b2 | ||
|
6f4e01f92d | ||
|
71a1f95cba | ||
|
f899a6aaad | ||
|
6c5486c227 | ||
|
dd323fb8dc | ||
|
6ee845ba60 | ||
|
5d027c8012 | ||
|
e23bf00919 | ||
|
cfc80a9d6e | ||
|
a014df24c5 | ||
|
c68a5e449f | ||
|
3242caee6a | ||
|
ae5dec259f | ||
|
3b35392d13 | ||
|
27dcf14de4 | ||
|
cabc7d32da | ||
|
26af53173e | ||
|
b69aab2431 | ||
|
cf929ce541 | ||
|
bb9c771f4f | ||
|
886d37792c | ||
|
77d127249c | ||
|
cfea73392b | ||
|
02585a58e3 | ||
|
4cf5d1965f | ||
|
06ad9c62b5 | ||
|
30a9249dd9 | ||
|
c1a028c345 | ||
|
4100770e32 | ||
|
f944220634 | ||
|
ad1b9e1b07 | ||
|
197b49677d | ||
|
9582a7970e | ||
|
957e8ab4be | ||
|
8b171279e9 | ||
|
4a98dbdcd9 | ||
|
e2029649b9 | ||
|
c0ac498159 | ||
|
a29518b978 | ||
|
001f827a4f | ||
|
24e702e6cd | ||
|
d26d7a7959 | ||
|
5ddf120260 | ||
|
93336bb110 | ||
|
8ee19a09e2 | ||
|
0398e228de | ||
|
a177dbaae4 | ||
|
4c31e0c81f | ||
|
c5f5a4c038 | ||
|
5e2751fe85 | ||
|
294cf98f59 | ||
|
dce16514fe | ||
|
7df8f7e215 | ||
|
9e9366bbef | ||
|
c685525849 | ||
|
32c6eb989c | ||
|
e8a7e1f12b | ||
|
987e447551 | ||
|
d61a1ce875 | ||
|
f9fc3f356f | ||
|
d298a11af7 | ||
|
d3fd2d9a10 | ||
|
d3f8ea684e | ||
|
3d6e4e7c2e | ||
|
6a1d268315 | ||
|
2a988a2021 | ||
|
6b229c3ae2 | ||
|
79af2e7fdf | ||
|
dbef5838d4 | ||
|
80f58d05f0 | ||
|
4449dd088b | ||
|
29c7d98898 | ||
|
0ce2b3927e | ||
|
501a539c22 | ||
|
156dd01575 | ||
|
24df5ea742 | ||
|
c0d8f1807d | ||
|
bdb0e9d37d | ||
|
c1a4ad1ab1 | ||
|
61daaffee6 | ||
|
416d89268e | ||
|
391360f145 | ||
|
f429960d58 | ||
|
a77ea02b8d | ||
|
acb45eeb84 | ||
|
694abbcafa | ||
|
5105fc4981 | ||
|
b9d80939c6 | ||
|
1b061d63a8 | ||
|
8adde8d9c7 | ||
|
a0194d7ffd | ||
|
ba3fb44b49 | ||
|
70406170f5 | ||
|
4ad7e911d9 | ||
|
0816a04f42 | ||
|
83c23c7a3a | ||
|
d71f4c279b | ||
|
3293100c42 | ||
|
00d311d90f | ||
|
326399794e | ||
|
691395e193 | ||
|
c167627675 | ||
|
4b11437f7a | ||
|
2895ca34dd | ||
|
0be2a2ced3 | ||
|
b614cdbd6e | ||
|
db5f82be2a | ||
|
b38e904a4e | ||
|
32419c899c | ||
|
63fd27fbce | ||
|
7b03a01b18 | ||
|
1137ed5f07 | ||
|
32343842d3 | ||
|
ad50594cb2 | ||
|
f57d661416 | ||
|
98eead0058 | ||
|
da4d1d06d4 | ||
|
e854f357f4 | ||
|
78503bf574 | ||
|
01cbb31770 | ||
|
47163784d7 | ||
|
3e6a86b6b8 | ||
|
b1abd13319 | ||
|
ee536fd995 | ||
|
d58e20ee65 | ||
|
159e144abf | ||
|
8871dcd2e1 | ||
|
df794c0181 | ||
|
5f18ebc705 | ||
|
be55b9c98d | ||
|
aec63cd2e6 | ||
|
89800d4341 | ||
|
f4b2eb0ced | ||
|
b435c1b87b | ||
|
7ba0ee591e | ||
|
d320ef4fdb | ||
|
28245c731e | ||
|
19ec49f89a | ||
|
57878ff44f |
3
.arcconfig
Normal file
3
.arcconfig
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"phabricator.uri" : "https://phabricator.kde.org/"
|
||||
}
|
99
.clang-format
Normal file
99
.clang-format
Normal 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
2
.git-blame-ignore-revs
Normal file
@ -0,0 +1,2 @@
|
||||
# _clang_format added
|
||||
f62a8ee8f7e81a1b573c335ded3326d8ee985ab4
|
50
.gitlab-ci.yml
Normal file
50
.gitlab-ci.yml
Normal 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
|
203
CMakeLists.txt
203
CMakeLists.txt
@ -1,28 +1,25 @@
|
||||
# Checking for user explicity defined CMAKE_INSTALL_PREFIX
|
||||
# Checking for user explicitly defined CMAKE_INSTALL_PREFIX
|
||||
# It must be done before project(...)
|
||||
if(NOT CMAKE_INSTALL_PREFIX)
|
||||
set(QCA_INSTALL_IN_QT_PREFIX ON)
|
||||
# If CMAKE_INSTALL_PREFIX is set in cmake arguments
|
||||
unset(CMAKE_INSTALL_PREFIX CACHE)
|
||||
endif(NOT CMAKE_INSTALL_PREFIX)
|
||||
endif()
|
||||
|
||||
# The cmake min. version should be set before calling project(...) too
|
||||
cmake_minimum_required(VERSION 3.4)
|
||||
|
||||
project(qca)
|
||||
|
||||
if(NOT APPLE)
|
||||
cmake_minimum_required(VERSION 2.8.12)
|
||||
else()
|
||||
cmake_minimum_required(VERSION 3.0)
|
||||
endif()
|
||||
|
||||
set(QCA_LIB_MAJOR_VERSION "2")
|
||||
set(QCA_LIB_MINOR_VERSION "1")
|
||||
set(QCA_LIB_PATCH_VERSION "1")
|
||||
set(QCA_LIB_MINOR_VERSION "3")
|
||||
set(QCA_LIB_PATCH_VERSION "3")
|
||||
|
||||
# Do not automatically link Qt executables to qtmain target on Windows.
|
||||
# QCA exucatables use console mode only. Not need to link against
|
||||
# qtmain.lib.
|
||||
cmake_policy(SET CMP0020 OLD)
|
||||
#if(POLICY CMP0042)
|
||||
# cmake_policy(SET CMP0042 OLD)
|
||||
#endif()
|
||||
|
||||
option(QT6 "Build with Qt 6" OFF)
|
||||
option(BUILD_TESTS "Create test" ON)
|
||||
option(BUILD_TOOLS "Compile mozcerts and qcatool" ON)
|
||||
set(BUILD_PLUGINS "auto" CACHE STRING "Plugins for building (also possible values: none, all and auto)")
|
||||
@ -41,44 +38,32 @@ find_package(Doxygen)
|
||||
string(TOLOWER "${BUILD_PLUGINS}" BUILD_PLUGINS)
|
||||
if(NOT BUILD_PLUGINS)
|
||||
set(BUILD_PLUGINS "none")
|
||||
endif(NOT BUILD_PLUGINS)
|
||||
endif()
|
||||
|
||||
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules" )
|
||||
|
||||
option(QT4_BUILD "Force building with Qt4 even if Qt5 is found")
|
||||
if (NOT QT4_BUILD)
|
||||
find_package(Qt5Core QUIET)
|
||||
mark_as_advanced(Qt5Core_DIR)
|
||||
# Do not automatically link Qt executables to qtmain target on Windows.
|
||||
# QCA exucatables use console mode only. Not need to link against qtmain.lib.
|
||||
if(QT6)
|
||||
message(STATUS "Building Qt 6 version")
|
||||
find_package(Qt6 COMPONENTS Core Test Core5Compat REQUIRED)
|
||||
else()
|
||||
message(STATUS "Building Qt 5 version")
|
||||
set(Qt5_NO_LINK_QTMAIN ON)
|
||||
find_package(Qt5 5.14 REQUIRED Core)
|
||||
endif()
|
||||
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
|
||||
include(QcaMacro)
|
||||
|
||||
if (Qt5Core_FOUND)
|
||||
message(STATUS "Building with Qt5 support")
|
||||
# Got from ECM
|
||||
# Distros have no ECM. So I just copied required cmake modules.
|
||||
find_package(Qt5Transitional REQUIRED Core Network)
|
||||
include(ECMQt4To5Porting)
|
||||
|
||||
include(GNUInstallDirs)
|
||||
setup_qt5_dirs()
|
||||
include(GNUInstallDirs)
|
||||
setup_qt_dirs()
|
||||
if(QT6)
|
||||
set(QCA_QT_PC_VERSION "Qt6Core")
|
||||
set(QCA_SUFFIX "qt6")
|
||||
else()
|
||||
set(QCA_QT_PC_VERSION "Qt5Core")
|
||||
set(QCA_SUFFIX "qt5")
|
||||
else()
|
||||
set(QT_MIN_VERSION "4.7.0")
|
||||
set(QT_USE_IMPORTED_TARGETS ON)
|
||||
if(BUILD_TESTS)
|
||||
find_package(Qt4 REQUIRED QtCore QtNetwork QtTest)
|
||||
else(BUILD_TESTS)
|
||||
find_package(Qt4 REQUIRED QtCore)
|
||||
endif(BUILD_TESTS)
|
||||
# WORKAROUND: Seems it must be done in Qt4 find module but didn't
|
||||
mark_as_advanced(QT_QMAKE_EXECUTABLE)
|
||||
|
||||
# properly set up compile flags (QT_DEBUG/QT_NO_DEBUG, ...)
|
||||
include(${QT_USE_FILE})
|
||||
setup_qt4_dirs()
|
||||
set(QCA_QT_PC_VERSION "QtCore")
|
||||
endif()
|
||||
|
||||
# QCA can be shared but plugins will be static
|
||||
@ -87,9 +72,9 @@ if(NOT BUILD_SHARED_LIBS OR QT_IS_STATIC)
|
||||
set(STATIC_PLUGINS ON)
|
||||
add_definitions(-DQT_STATICPLUGIN)
|
||||
set(PLUGIN_TYPE "STATIC")
|
||||
else(NOT BUILD_SHARED_LIBS OR QT_IS_STATIC)
|
||||
else()
|
||||
set(PLUGIN_TYPE "MODULE")
|
||||
endif(NOT BUILD_SHARED_LIBS OR QT_IS_STATIC)
|
||||
endif()
|
||||
|
||||
set(QCA_SUFFIX "${QCA_SUFFIX}" CACHE STRING "QCA common suffix")
|
||||
if(QCA_SUFFIX)
|
||||
@ -98,13 +83,13 @@ if(QCA_SUFFIX)
|
||||
set(MOZCERTS_NAME mozcerts-${QCA_SUFFIX})
|
||||
set(QCA_PC_NAME qca2-${QCA_SUFFIX}.pc)
|
||||
set(QCA_CONFIG_NAME_BASE "Qca-${QCA_SUFFIX}")
|
||||
else(QCA_SUFFIX)
|
||||
else()
|
||||
set(QCA_LIB_NAME qca)
|
||||
set(QCA_TOOL_NAME qcatool)
|
||||
set(MOZCERTS_NAME mozcerts)
|
||||
set(QCA_PC_NAME qca2.pc)
|
||||
set(QCA_CONFIG_NAME_BASE "Qca")
|
||||
endif(QCA_SUFFIX)
|
||||
endif()
|
||||
|
||||
set(QCA_LIB_VERSION_STRING "${QCA_LIB_MAJOR_VERSION}.${QCA_LIB_MINOR_VERSION}.${QCA_LIB_PATCH_VERSION}")
|
||||
|
||||
@ -115,9 +100,9 @@ if (WIN32)
|
||||
add_definitions(-DWIN32_LEAN_AND_MEAN)
|
||||
elseif (APPLE)
|
||||
set(CMAKE_DEBUG_POSTFIX "_debug")
|
||||
endif (WIN32)
|
||||
endif()
|
||||
|
||||
if (CMAKE_COMPILER_IS_GNUCXX)
|
||||
if (CMAKE_CXX_COMPILER_ID MATCHES "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
if (CMAKE_SYSTEM_NAME MATCHES Linux)
|
||||
add_definitions (-D_DEFAULT_SOURCE)
|
||||
# on arm -Wcast-align throws many internal qt warning
|
||||
@ -126,12 +111,31 @@ if (CMAKE_COMPILER_IS_GNUCXX)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wcast-align")
|
||||
endif()
|
||||
|
||||
set ( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-long-long -ansi -Wundef -Werror-implicit-function-declaration -Wchar-subscripts -Wall -W -Wpointer-arith -Wwrite-strings -Wformat-security -Wmissing-format-attribute -fno-common")
|
||||
set ( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wnon-virtual-dtor -Wno-long-long -ansi -Wundef -Wchar-subscripts -Wall -W -Wpointer-arith -Wwrite-strings -Wformat-security -fno-check-new -fno-common")
|
||||
endif (CMAKE_SYSTEM_NAME MATCHES Linux)
|
||||
endif (CMAKE_COMPILER_IS_GNUCXX)
|
||||
set ( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-long-long -Wundef -Werror-implicit-function-declaration -Wchar-subscripts -Wall -W -Wpointer-arith -Wwrite-strings -Wformat-security -Wmissing-format-attribute -fno-common")
|
||||
set ( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wnon-virtual-dtor -Wno-long-long -Wundef -Wchar-subscripts -Wall -W -Wpointer-arith -Wwrite-strings -Wformat-security -fno-check-new -fno-common")
|
||||
|
||||
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wsuggest-override -Wlogical-op" )
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
add_definitions(-DQT_NO_CAST_TO_ASCII
|
||||
-DQT_NO_CAST_FROM_ASCII
|
||||
-DQT_NO_URL_CAST_FROM_STRING
|
||||
-DQT_NO_CAST_FROM_BYTEARRAY
|
||||
-DQT_NO_SIGNALS_SLOTS_KEYWORDS
|
||||
-DQT_USE_QSTRINGBUILDER
|
||||
-DQT_NO_NARROWING_CONVERSIONS_IN_CONNECT)
|
||||
|
||||
if (NOT WIN32)
|
||||
# Strict iterators can't be used on Windows, they lead to a link error
|
||||
# when application code iterates over a QVector<QPoint> for instance, unless
|
||||
# Qt itself was also built with strict iterators.
|
||||
# See example at https://bugreports.qt.io/browse/AUTOSUITE-946
|
||||
add_definitions(-DQT_STRICT_ITERATORS)
|
||||
endif()
|
||||
|
||||
add_definitions (${QT_DEFINITIONS})
|
||||
include_directories("include/QtCrypto/")
|
||||
# for generated files
|
||||
include_directories(${CMAKE_BINARY_DIR})
|
||||
@ -178,7 +182,7 @@ if( QCA_INSTALL_IN_QT_PREFIX )
|
||||
endif()
|
||||
set(QCA_DOC_INSTALL_DIR "${QT_DOC_DIR}/html/qca/" CACHE PATH "Directory where qca documentation will install")
|
||||
set(QCA_MAN_INSTALL_DIR "${QT_DATA_DIR}/man" CACHE PATH "Directory where qca man pages will install")
|
||||
else( QCA_INSTALL_IN_QT_PREFIX )
|
||||
else()
|
||||
# Cmake says nothing about LIB_SUFFIX
|
||||
# de facto it is a standard way to specify lib suffix on many distros
|
||||
set(LIB_SUFFIX "" CACHE STRING "Define suffix of directory name (32/64)" )
|
||||
@ -198,7 +202,7 @@ else( QCA_INSTALL_IN_QT_PREFIX )
|
||||
endif()
|
||||
set(QCA_DOC_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/share/doc/${QCA_LIB_NAME}/html" CACHE PATH "Directory where qca documentation will install")
|
||||
set(QCA_MAN_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/share/man" CACHE PATH "Directory where qca man pages will install")
|
||||
endif( QCA_INSTALL_IN_QT_PREFIX )
|
||||
endif()
|
||||
|
||||
set(PKGCONFIG_INSTALL_PREFIX "${QCA_LIBRARY_INSTALL_DIR}/pkgconfig" CACHE PATH "Base directory for pkgconfig files")
|
||||
|
||||
@ -242,12 +246,14 @@ if(NOT WIN32)
|
||||
set(PKGCONFIG_LIBS "-L\${libdir} -l${QCA_LIB_NAME}")
|
||||
endif()
|
||||
|
||||
# qca2.pc uses absolute paths. So it must be there. Don't rellocate this.
|
||||
configure_file("qca2.pc.cmake" "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/pkgconfig/${QCA_PC_NAME}" @ONLY)
|
||||
if(NOT DEVELOPER_MODE)
|
||||
install(FILES "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/pkgconfig/${QCA_PC_NAME}" DESTINATION ${PKGCONFIG_INSTALL_PREFIX})
|
||||
if(NOT QT6)
|
||||
# qca2.pc uses absolute paths. So it must be there. Don't rellocate this.
|
||||
configure_file("qca2.pc.cmake" "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/pkgconfig/${QCA_PC_NAME}" @ONLY)
|
||||
if(NOT DEVELOPER_MODE)
|
||||
install(FILES "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/pkgconfig/${QCA_PC_NAME}" DESTINATION ${PKGCONFIG_INSTALL_PREFIX})
|
||||
endif()
|
||||
endif()
|
||||
endif(NOT WIN32)
|
||||
endif()
|
||||
|
||||
# strip CMAKE_INSTALL_PREFIX in all paths
|
||||
if(USE_RELATIVE_PATHS)
|
||||
@ -283,20 +289,18 @@ endif()
|
||||
|
||||
if (APPLE)
|
||||
set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
|
||||
endif (APPLE)
|
||||
endif()
|
||||
|
||||
message(STATUS "Checking for certstore..")
|
||||
# fixme add OR mac
|
||||
if( WIN32 )
|
||||
# USE BUILTIN
|
||||
else ( WIN32 )
|
||||
# USE BUILTIN
|
||||
else()
|
||||
if ( DEFINED ENV{QC_CERTSTORE_PATH} )
|
||||
if(EXISTS $ENV{QC_CERTSTORE_PATH})
|
||||
set( qca_CERTSTORE $ENV{QC_CERTSTORE_PATH})
|
||||
else(EXISTS $ENV{QC_CERTSTORE_PATH})
|
||||
# path to try
|
||||
endif(EXISTS $ENV{QC_CERTSTORE_PATH})
|
||||
else( DEFINED ENV{QC_CERTSTORE_PATH} )
|
||||
endif()
|
||||
else()
|
||||
set( toTry
|
||||
"/etc/ssl/certs/ca-certificates.crt"
|
||||
"/usr/share/ssl/cert.pem"
|
||||
@ -308,21 +312,21 @@ else ( WIN32 )
|
||||
foreach (_current_try ${toTry})
|
||||
if(EXISTS ${_current_try})
|
||||
set( qca_CERTSTORE ${_current_try})
|
||||
endif(EXISTS ${_current_try})
|
||||
endif()
|
||||
endforeach (_current_try)
|
||||
endif( DEFINED ENV{QC_CERTSTORE_PATH} )
|
||||
endif(WIN32)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (qca_CERTSTORE)
|
||||
message(STATUS "Found system certstore")
|
||||
else (qca_CERTSTORE)
|
||||
else()
|
||||
message(STATUS "Using built in certstore.")
|
||||
set( qca_CERTSTORE "${CMAKE_CURRENT_SOURCE_DIR}/certs/rootcerts.pem")
|
||||
# note that INSTALL_FILES targets are relative to the current installation prefix...
|
||||
if(NOT DEVELOPER_MODE)
|
||||
install(FILES "${qca_CERTSTORE}" DESTINATION "${QCA_PREFIX_INSTALL_DIR}/certs")
|
||||
endif()
|
||||
endif (qca_CERTSTORE)
|
||||
endif()
|
||||
message(STATUS "certstore path: " ${qca_CERTSTORE})
|
||||
add_definitions( -DQCA_SYSTEMSTORE_PATH="${qca_CERTSTORE}" )
|
||||
|
||||
@ -350,11 +354,13 @@ set( public_HEADERS
|
||||
|
||||
set( qca_HEADERS ${private_HEADERS} ${public_HEADERS} )
|
||||
|
||||
include_directories(${QT_QTCORE_INCLUDE_DIR} "${qca_INCLUDEDIR}/QtCrypto")
|
||||
include_directories("${qca_INCLUDEDIR}/QtCrypto")
|
||||
|
||||
configure_file("crypto.prf.cmake" "${CMAKE_BINARY_DIR}/mkspecs/features/crypto.prf" @ONLY)
|
||||
if(NOT DEVELOPER_MODE)
|
||||
install(FILES "${CMAKE_BINARY_DIR}/mkspecs/features/crypto.prf" DESTINATION "${QCA_FEATURE_INSTALL_DIR}")
|
||||
if(NOT QT6)
|
||||
configure_file("crypto.prf.cmake" "${CMAKE_BINARY_DIR}/mkspecs/features/crypto.prf" @ONLY)
|
||||
if(NOT DEVELOPER_MODE)
|
||||
install(FILES "${CMAKE_BINARY_DIR}/mkspecs/features/crypto.prf" DESTINATION "${QCA_FEATURE_INSTALL_DIR}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
configure_file(man/qcatool.1 "${CMAKE_BINARY_DIR}/share/man/man1/${QCA_TOOL_NAME}.1" COPYONLY)
|
||||
@ -374,29 +380,29 @@ if(STATIC_PLUGINS)
|
||||
if(WITH_${PLUGIN}_PLUGIN_INTERNAL)
|
||||
string(REPLACE "-" "_" IMPORT_NAME "qca-${PLUGIN}")
|
||||
file(APPEND "${CMAKE_BINARY_DIR}/import_plugins.h" "Q_IMPORT_PLUGIN(${IMPORT_NAME})\n")
|
||||
endif(WITH_${PLUGIN}_PLUGIN_INTERNAL)
|
||||
endif()
|
||||
endforeach(PLUGIN IN LISTS PLUGINS)
|
||||
endif(STATIC_PLUGINS)
|
||||
endif()
|
||||
|
||||
if(BUILD_TESTS)
|
||||
enable_testing()
|
||||
add_subdirectory(unittest)
|
||||
add_subdirectory(examples)
|
||||
endif(BUILD_TESTS)
|
||||
endif()
|
||||
if(BUILD_TOOLS)
|
||||
add_subdirectory(tools)
|
||||
endif(BUILD_TOOLS)
|
||||
endif()
|
||||
|
||||
if(DOXYGEN_FOUND)
|
||||
configure_file(${CMAKE_SOURCE_DIR}/Doxyfile.in ${CMAKE_BINARY_DIR}/Doxyfile @ONLY)
|
||||
add_custom_target(doc
|
||||
${DOXYGEN_EXECUTABLE} ${CMAKE_BINARY_DIR}/Doxyfile
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/images
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_SOURCE_DIR}/images/qca-arch.eps ${CMAKE_BINARY_DIR}/images/qca-arch.eps
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_SOURCE_DIR}/images/qca-arch.png ${CMAKE_BINARY_DIR}/images/qca-arch.png
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||
COMMENT "Generating API documentation with Doxygen" VERBATIM)
|
||||
endif(DOXYGEN_FOUND)
|
||||
#if(DOXYGEN_FOUND)
|
||||
# configure_file(${CMAKE_SOURCE_DIR}/Doxyfile.in ${CMAKE_BINARY_DIR}/Doxyfile @ONLY)
|
||||
# add_custom_target(doc
|
||||
# ${DOXYGEN_EXECUTABLE} ${CMAKE_BINARY_DIR}/Doxyfile
|
||||
# COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/docs/pics
|
||||
# COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_SOURCE_DIR}/docs/pics/qca-arch.eps ${CMAKE_BINARY_DIR}/docs/pics/qca-arch.eps
|
||||
# COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_SOURCE_DIR}/docs/pics/qca-arch.png ${CMAKE_BINARY_DIR}/docs/pics/qca-arch.png
|
||||
# WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||
# COMMENT "Generating API documentation with Doxygen" VERBATIM)
|
||||
#endif()
|
||||
|
||||
include(CMakePackageConfigHelpers)
|
||||
configure_package_config_file(
|
||||
@ -426,7 +432,7 @@ if(NOT DEVELOPER_MODE)
|
||||
message("!! you MUST explicity define CMAKE_INSTALL_PREFIX !!")
|
||||
message("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")
|
||||
message("${ESCAPE}[0m")
|
||||
endif(QCA_INSTALL_IN_QT_PREFIX)
|
||||
endif()
|
||||
|
||||
message("")
|
||||
if(USE_RELATIVE_PATHS)
|
||||
@ -463,11 +469,16 @@ if(NOT DEVELOPER_MODE)
|
||||
message("")
|
||||
|
||||
if(UNIX AND NOT APPLE)
|
||||
if(NOT QCA_SUFFIX AND NOT QT4_BUILD)
|
||||
if(NOT QCA_SUFFIX)
|
||||
|
||||
message("${ESCAPE}[31mYou don't have QCA_SUFFIX set. Please note that the recommended way of")
|
||||
message("building Qt5 version of qca for Linux distributions is to set")
|
||||
message("QCA_SUFFIX to qt5 (-DQCA_SUFFIX=qt5).")
|
||||
if(QT6)
|
||||
message("building Qt6 version of qca for Linux distributions is to set")
|
||||
message("QCA_SUFFIX to qt6 (-DQCA_SUFFIX=qt6).")
|
||||
else()
|
||||
message("building Qt5 version of qca for Linux distributions is to set")
|
||||
message("QCA_SUFFIX to qt5 (-DQCA_SUFFIX=qt5).")
|
||||
endif()
|
||||
message("${ESCAPE}[0m")
|
||||
endif()
|
||||
endif()
|
||||
|
@ -567,7 +567,7 @@ EXAMPLE_RECURSIVE = NO
|
||||
# directories that contain image that are included in the documentation (see
|
||||
# the \image command).
|
||||
|
||||
IMAGE_PATH = @CMAKE_SOURCE_DIR@/images
|
||||
IMAGE_PATH = @CMAKE_SOURCE_DIR@/docs/pics
|
||||
|
||||
# The INPUT_FILTER tag can be used to specify a program that doxygen should
|
||||
# invoke to filter for each input file. Doxygen will invoke the filter program
|
||||
@ -1070,7 +1070,7 @@ PREDEFINED = DOXYGEN_SHOULD_SKIP_THIS \
|
||||
# The macro definition that is found in the sources will be used.
|
||||
# Use the PREDEFINED tag if you want to use a different macro definition.
|
||||
|
||||
EXPAND_AS_DEFINED = QCA_EXPORT
|
||||
EXPAND_AS_DEFINED = QCA_EXPORT QCA_NOEXCEPT
|
||||
|
||||
# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
|
||||
# doxygen's preprocessor will remove all function-like macros that are alone
|
||||
|
11
INSTALL
11
INSTALL
@ -1,7 +1,7 @@
|
||||
Installing QCA
|
||||
--------------
|
||||
|
||||
QCA requires Qt 4.7 or greater.
|
||||
QCA requires Qt 5.5 or greater.
|
||||
|
||||
For Unix/Linux/Mac/Windows:
|
||||
|
||||
@ -17,7 +17,6 @@ Notes
|
||||
|
||||
CMAKE_INSTALL_PREFIX - must be defined otherwise QCA will be installed
|
||||
in Qt prefix (by default: "")
|
||||
QT4_BUILD - forced Qt4 building (by default: OFF)
|
||||
BUILD_TESTS - build unittests (by default: ON)
|
||||
BUILD_TOOLS - build mozcerts and qcatool (by default: ON)
|
||||
QCA_SUFFIX - suffix will be used for library, qcatool binary,
|
||||
@ -53,10 +52,4 @@ Please report problems to:
|
||||
http://bugs.kde.org
|
||||
|
||||
Official git repo:
|
||||
http://quickgit.kde.org/?p=qca.git
|
||||
|
||||
KDE Projects page:
|
||||
http://projects.kde.org/projects/kdesupport/qca
|
||||
|
||||
Official homepage:
|
||||
http://delta.affinix.com/qca/
|
||||
https://invent.kde.org/kde/qca
|
||||
|
@ -150,9 +150,9 @@
|
||||
\subsection qca2code Releases
|
||||
|
||||
The latest release packages can be found in the
|
||||
<a href="http://delta.affinix.com/download/qca/2.0/">%QCA 2.0 download area</a>.
|
||||
<a href="https://download.kde.org/stable/qca/">%QCA 2.x download area</a>.
|
||||
|
||||
See the <a href="http://delta.affinix.com/qca/">project web site</a> for
|
||||
See the <a href="https://userbase.kde.org/QCA/">project web site</a> for
|
||||
further information about %QCA releases.
|
||||
|
||||
\subsection qca2dev Current development
|
||||
@ -163,12 +163,12 @@
|
||||
to build and use %QCA.
|
||||
|
||||
The Git code can be browsed
|
||||
<a href="http://quickgit.kde.org/?p=qca.git">
|
||||
<a href="https://commits.kde.org/qca">
|
||||
via the web</a>
|
||||
|
||||
Use
|
||||
\verbatim
|
||||
git clone git://anongit.kde.org/qca.git
|
||||
git clone https://invent.kde.org/libraries/qca.git
|
||||
\endverbatim
|
||||
to get the latest sources.
|
||||
*/
|
||||
|
75
README
75
README
@ -1,26 +1,19 @@
|
||||
Qt Cryptographic Architecture (QCA) version 2.1.0
|
||||
-------------------------------------------------
|
||||
Date: November 6th, 2014
|
||||
Website: http://delta.affinix.com/qca/
|
||||
Mailing List: Delta Project <delta@lists.affinix.com>
|
||||
Qt Cryptographic Architecture (QCA)
|
||||
-----------------------------------
|
||||
|
||||
Project Lead/Maintainer (2003-current):
|
||||
Justin Karneges <justin@affinix.com>
|
||||
(March 2007 - August 2007 under Barracuda Networks employment)
|
||||
Description
|
||||
-----------
|
||||
|
||||
Development, Documentation, Unittests (2004-2009):
|
||||
Brad Hards <bradh@frogmouth.net>
|
||||
QCA is a library that provides an easy API for a range of cryptographic
|
||||
features, including SSL/TLS, X.509 certificates, SASL, OpenPGP, smartcards,
|
||||
and much more.
|
||||
|
||||
Development (2013-current)
|
||||
Ivan Romanov <drizt@land.ru>
|
||||
Functionality is supplied via plugins. This is useful for avoiding
|
||||
dependence on a particular crypto library and makes upgrading easier,
|
||||
as there is no need to recompile your application when adding or
|
||||
upgrading a crypto plugin.
|
||||
|
||||
Special Thanks:
|
||||
Portugal Telecom (SAPO division), for sponsorship
|
||||
Alon Bar-Lev, for smart card and design assistance
|
||||
Jack Lloyd, for Botan and X.509 mentoring
|
||||
L. Peter Deutsch, for the public domain MD5 implementation
|
||||
Steve Reid, for the public domain SHA1 implementation
|
||||
Jason Kim, for the CMS Signer graphics
|
||||
In order for QCA to be of much use, you'll want to install some plugins.
|
||||
|
||||
|
||||
Install
|
||||
@ -34,8 +27,16 @@ License
|
||||
the COPYING file for more information.
|
||||
|
||||
|
||||
Changes
|
||||
History
|
||||
-------
|
||||
|
||||
QCA was originally created to support the security needs of the
|
||||
Psi XMPP/Jabber client project ( http://psi-im.org/ ).
|
||||
|
||||
|
||||
Old Changes list
|
||||
----------------
|
||||
|
||||
New in 2.1.0
|
||||
- Ported to Qt5 (Qt4 also supported)
|
||||
- New building system. CMake instead of qmake
|
||||
@ -90,25 +91,23 @@ Changes
|
||||
- Windows version can be configured/installed using paths with spaces
|
||||
|
||||
|
||||
Description
|
||||
-----------
|
||||
Old Developer list
|
||||
------------------
|
||||
|
||||
QCA is a library that provides an easy API for a range of cryptographic
|
||||
features, including SSL/TLS, X.509 certificates, SASL, OpenPGP, smartcards,
|
||||
and much more.
|
||||
Project Lead/Maintainer (2003-2012):
|
||||
Justin Karneges <justin@affinix.com>
|
||||
(March 2007 - August 2007 under Barracuda Networks employment)
|
||||
|
||||
Functionality is supplied via plugins. This is useful for avoiding
|
||||
dependence on a particular crypto library and makes upgrading easier,
|
||||
as there is no need to recompile your application when adding or
|
||||
upgrading a crypto plugin.
|
||||
Development, Documentation, Unittests (2004-2009):
|
||||
Brad Hards <bradh@frogmouth.net>
|
||||
|
||||
In order for QCA to be of much use, you'll want to install some plugins.
|
||||
Development (2013-2017)
|
||||
Ivan Romanov <drizt@land.ru>
|
||||
|
||||
QCA was originally created to support the security needs of the
|
||||
Psi XMPP/Jabber client project ( http://psi-im.org/ ).
|
||||
|
||||
API Documentation is located in the 'apidocs' subdirectory.
|
||||
|
||||
|
||||
Have fun,
|
||||
-Justin
|
||||
Special Thanks:
|
||||
Portugal Telecom (SAPO division), for sponsorship
|
||||
Alon Bar-Lev, for smart card and design assistance
|
||||
Jack Lloyd, for Botan and X.509 mentoring
|
||||
L. Peter Deutsch, for the public domain MD5 implementation
|
||||
Steve Reid, for the public domain SHA1 implementation
|
||||
Jason Kim, for the CMS Signer graphics
|
||||
|
14
README.clang-format
Normal file
14
README.clang-format
Normal 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 :)
|
@ -1,5 +1,5 @@
|
||||
rootcerts.pem is created by qca/tools/mozcerts
|
||||
|
||||
File: mozilla/security/nss/lib/ckfw/builtins/certdata.txt
|
||||
Date: January 15th, 2009
|
||||
File: https://hg.mozilla.org/mozilla-central/log/tip/security/nss/lib/ckfw/builtins/certdata.txt
|
||||
Date: July 4, 2020
|
||||
|
||||
|
5093
certs/rootcerts.pem
5093
certs/rootcerts.pem
File diff suppressed because it is too large
Load Diff
@ -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()
|
@ -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)
|
||||
|
||||
|
@ -1,13 +0,0 @@
|
||||
# Copyright (c) 2014, Samuel Gaist, <samuel.gaist@edeltech.ch>
|
||||
#
|
||||
# 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(CoreFoundation)
|
||||
|
||||
if (CoreFoundation_FRAMEWORKS)
|
||||
set(COREFOUNDATION_LIBRARY "-framework CoreFoundation" CACHE FILEPATH "CoreFoundation framework" FORCE)
|
||||
set(COREFOUNDATION_FOUND 1)
|
||||
endif (CoreFoundation_FRAMEWORKS)
|
@ -42,11 +42,11 @@ ENDIF(LIBGCRYPTCONFIG_EXECUTABLE)
|
||||
if (LIBGCRYPT_FOUND)
|
||||
if (NOT LibGcrypt_FIND_QUIETLY)
|
||||
message(STATUS "Found libgcrypt: ${LIBGCRYPT_LIBRARIES}")
|
||||
endif (NOT LibGcrypt_FIND_QUIETLY)
|
||||
else (LIBGCRYPT_FOUND)
|
||||
endif()
|
||||
else()
|
||||
if (LibGcrypt_FIND_REQUIRED)
|
||||
message(FATAL_ERROR "Could not find libgcrypt libraries")
|
||||
endif (LibGcrypt_FIND_REQUIRED)
|
||||
endif (LIBGCRYPT_FOUND)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
MARK_AS_ADVANCED(LIBGCRYPT_CFLAGS LIBGCRYPT_LIBRARIES)
|
||||
|
@ -1,37 +0,0 @@
|
||||
# - Try to find the NSS library
|
||||
# Once done this will define
|
||||
#
|
||||
# NSS_FOUND - system has mozilla-nss lib
|
||||
# NSS_INCLUDE_DIRS - the mozilla-nss include directories
|
||||
# NSS_LDFLAGS - Link these to use mozilla-nss
|
||||
# NSS_CFLAGS_OTHER - Compiler switches required for using NSS
|
||||
#
|
||||
# Copyright (c) 2006, Laurent Montel, <montel@kde.org>
|
||||
#
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||
|
||||
if(NSS_INCLUDE_DIRS AND NSS_LDFLAGS)
|
||||
|
||||
# in cache already
|
||||
SET(NSS_FOUND TRUE)
|
||||
|
||||
else()
|
||||
if(NOT WIN32)
|
||||
find_package(PkgConfig)
|
||||
pkg_search_module(NSS nss)
|
||||
endif(NOT WIN32)
|
||||
|
||||
if (NSS_FOUND)
|
||||
if (NOT Nss_FIND_QUIETLY)
|
||||
message(STATUS "Found NSS: ${NSS_LDFLAGS}")
|
||||
endif (NOT Nss_FIND_QUIETLY)
|
||||
else (NSS_FOUND)
|
||||
if (Nss_FIND_REQUIRED)
|
||||
message(FATAL_ERROR "Could NOT find NSS")
|
||||
endif (Nss_FIND_REQUIRED)
|
||||
endif (NSS_FOUND)
|
||||
|
||||
mark_as_advanced(NSS_INCLUDE_DIRS NSS_LDFLAGS NSS_CFLAGS_OTHER)
|
||||
|
||||
endif()
|
@ -23,17 +23,17 @@ else()
|
||||
if(NOT WIN32)
|
||||
find_package(PkgConfig)
|
||||
pkg_search_module(PKCS11H libpkcs11-helper-1)
|
||||
endif(NOT WIN32)
|
||||
endif()
|
||||
|
||||
if (PKCS11H_FOUND)
|
||||
if (NOT Pkcs11Helper_FIND_QUIETLY)
|
||||
message(STATUS "Found pkcs11-helper: ${PKCS11H_LDFLAGS}")
|
||||
endif (NOT Pkcs11Helper_FIND_QUIETLY)
|
||||
else (PKCS11H_FOUND)
|
||||
endif()
|
||||
else()
|
||||
if (Pkcs11Helper_FIND_REQUIRED)
|
||||
message(FATAL_ERROR "Could NOT find pkcs11-helper")
|
||||
endif (Pkcs11Helper_FIND_REQUIRED)
|
||||
endif (PKCS11H_FOUND)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
mark_as_advanced(PKCS11H_INCLUDE_DIRS PKCS11H_LDFLAGS PKCS11H_CFLAGS_OTHER)
|
||||
|
||||
|
@ -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()
|
@ -14,7 +14,7 @@
|
||||
if (SASL2_INCLUDE_DIR)
|
||||
# Already in cache, be silent
|
||||
set(SASL2_FIND_QUIETLY TRUE)
|
||||
endif (SASL2_INCLUDE_DIR)
|
||||
endif()
|
||||
|
||||
FIND_PATH(SASL2_INCLUDE_DIR sasl/sasl.h)
|
||||
|
||||
@ -23,18 +23,18 @@ FIND_LIBRARY(SASL2_LIBRARIES NAMES sasl2)
|
||||
|
||||
if (SASL2_INCLUDE_DIR AND SASL2_LIBRARIES)
|
||||
set(SASL2_FOUND TRUE)
|
||||
endif (SASL2_INCLUDE_DIR AND SASL2_LIBRARIES)
|
||||
endif()
|
||||
|
||||
|
||||
if (SASL2_FOUND)
|
||||
if (NOT Sasl2_FIND_QUIETLY)
|
||||
message(STATUS "Found Sasl2: ${SASL2_LIBRARIES}")
|
||||
endif (NOT Sasl2_FIND_QUIETLY)
|
||||
else (SASL2_FOUND)
|
||||
endif()
|
||||
else()
|
||||
if (Sasl2_FIND_REQUIRED)
|
||||
message(FATAL_ERROR "Could not find sasl2 libraries")
|
||||
endif (Sasl2_FIND_REQUIRED)
|
||||
endif (SASL2_FOUND)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
||||
MARK_AS_ADVANCED(SASL2_INCLUDE_DIR SASL2_LIBRARIES)
|
||||
|
@ -1,63 +1,28 @@
|
||||
|
||||
IF (Qt5Core_FOUND)
|
||||
# FindQt4.cmake wasn't used, so define it here
|
||||
MACRO (QT4_GET_MOC_INC_DIRS _moc_INC_DIRS)
|
||||
SET(${_moc_INC_DIRS})
|
||||
GET_DIRECTORY_PROPERTY(_inc_DIRS INCLUDE_DIRECTORIES)
|
||||
|
||||
FOREACH(_current ${_inc_DIRS})
|
||||
SET(${_moc_INC_DIRS} ${${_moc_INC_DIRS}} "-I" ${_current})
|
||||
ENDFOREACH(_current ${_inc_DIRS})
|
||||
ENDMACRO(QT4_GET_MOC_INC_DIRS)
|
||||
|
||||
MACRO(SETUP_QT5_DIRS)
|
||||
MACRO(SETUP_QT_DIRS)
|
||||
if(QT6)
|
||||
GET_TARGET_PROPERTY(QMAKE_EXECUTABLE Qt6::qmake LOCATION)
|
||||
else()
|
||||
GET_TARGET_PROPERTY(QMAKE_EXECUTABLE ${Qt5Core_QMAKE_EXECUTABLE} LOCATION)
|
||||
EXEC_PROGRAM( ${QMAKE_EXECUTABLE} ARGS "-query QT_INSTALL_LIBS" OUTPUT_VARIABLE QT_LIBRARY_DIR )
|
||||
EXEC_PROGRAM( ${QMAKE_EXECUTABLE} ARGS "-query QT_INSTALL_PREFIX" OUTPUT_VARIABLE QT_PREFIX_DIR )
|
||||
EXEC_PROGRAM( ${QMAKE_EXECUTABLE} ARGS "-query QT_INSTALL_PLUGINS" OUTPUT_VARIABLE QT_PLUGINS_DIR )
|
||||
EXEC_PROGRAM( ${QMAKE_EXECUTABLE} ARGS "-query QT_INSTALL_BINS" OUTPUT_VARIABLE QT_BINARY_DIR )
|
||||
EXEC_PROGRAM( ${QMAKE_EXECUTABLE} ARGS "-query QT_INSTALL_HEADERS" OUTPUT_VARIABLE QT_HEADERS_DIR )
|
||||
EXEC_PROGRAM( ${QMAKE_EXECUTABLE} ARGS "-query QT_INSTALL_DOCS" OUTPUT_VARIABLE QT_DOC_DIR )
|
||||
EXEC_PROGRAM( ${QMAKE_EXECUTABLE} ARGS "-query QT_INSTALL_DATA" OUTPUT_VARIABLE QT_DATA_DIR )
|
||||
EXEC_PROGRAM( ${QMAKE_EXECUTABLE} ARGS "-query QT_HOST_DATA" OUTPUT_VARIABLE QT_ARCHDATA_DIR )
|
||||
SET( QT_MKSPECS_DIR "${QT_ARCHDATA_DIR}/mkspecs" )
|
||||
ENDMACRO(SETUP_QT5_DIRS)
|
||||
ELSE (Qt5Core_FOUND)
|
||||
# Cmake FindQt4 module doesn't provide QT_INSTALL_PREFIX and QT_INSTALL_DATA vars
|
||||
# It will be done here
|
||||
MACRO(SETUP_QT4_DIRS)
|
||||
_qt4_query_qmake(QT_INSTALL_PREFIX QT_PREFIX_DIR)
|
||||
_qt4_query_qmake(QT_INSTALL_DATA QT_DATA_DIR)
|
||||
ENDMACRO(SETUP_QT4_DIRS)
|
||||
ENDIF()
|
||||
|
||||
MACRO(MY_AUTOMOC _srcsList)
|
||||
# QT4_GET_MOC_INC_DIRS(_moc_INCS)
|
||||
FOREACH (_current_FILE ${${_srcsList}})
|
||||
GET_FILENAME_COMPONENT(_abs_FILE ${_current_FILE} ABSOLUTE)
|
||||
GET_FILENAME_COMPONENT(_basename ${_current_FILE} NAME_WE)
|
||||
SET(_moc ${CMAKE_CURRENT_BINARY_DIR}/${_basename}.moc)
|
||||
# SET(extra_moc_argument)
|
||||
# if(WIN32)
|
||||
# SET(extra_moc_argument -DWIN32)
|
||||
# endif(WIN32)
|
||||
QT4_GENERATE_MOC(${_abs_FILE} ${_moc})
|
||||
# ADD_CUSTOM_COMMAND(OUTPUT ${_moc}
|
||||
# COMMAND ${QT_MOC_EXECUTABLE}
|
||||
# ARGS ${extra_moc_argument} ${_moc_INCS} -o ${_moc} ${_abs_FILE}
|
||||
# DEPENDS ${_current_FILE}
|
||||
# )
|
||||
LIST(APPEND ${_srcsList} ${_moc})
|
||||
ENDFOREACH (_current_FILE)
|
||||
ENDMACRO(MY_AUTOMOC)
|
||||
endif()
|
||||
EXEC_PROGRAM( ${QMAKE_EXECUTABLE} ARGS "-query QT_INSTALL_LIBS" OUTPUT_VARIABLE QT_LIBRARY_DIR )
|
||||
EXEC_PROGRAM( ${QMAKE_EXECUTABLE} ARGS "-query QT_INSTALL_PREFIX" OUTPUT_VARIABLE QT_PREFIX_DIR )
|
||||
EXEC_PROGRAM( ${QMAKE_EXECUTABLE} ARGS "-query QT_INSTALL_PLUGINS" OUTPUT_VARIABLE QT_PLUGINS_DIR )
|
||||
EXEC_PROGRAM( ${QMAKE_EXECUTABLE} ARGS "-query QT_INSTALL_BINS" OUTPUT_VARIABLE QT_BINARY_DIR )
|
||||
EXEC_PROGRAM( ${QMAKE_EXECUTABLE} ARGS "-query QT_INSTALL_HEADERS" OUTPUT_VARIABLE QT_HEADERS_DIR )
|
||||
EXEC_PROGRAM( ${QMAKE_EXECUTABLE} ARGS "-query QT_INSTALL_DOCS" OUTPUT_VARIABLE QT_DOC_DIR )
|
||||
EXEC_PROGRAM( ${QMAKE_EXECUTABLE} ARGS "-query QT_INSTALL_DATA" OUTPUT_VARIABLE QT_DATA_DIR )
|
||||
EXEC_PROGRAM( ${QMAKE_EXECUTABLE} ARGS "-query QT_HOST_DATA" OUTPUT_VARIABLE QT_ARCHDATA_DIR )
|
||||
SET( QT_MKSPECS_DIR "${QT_ARCHDATA_DIR}/mkspecs" )
|
||||
ENDMACRO(SETUP_QT_DIRS)
|
||||
|
||||
macro(set_enabled_plugin PLUGIN ENABLED)
|
||||
# To nice looks
|
||||
if(ENABLED)
|
||||
set(ENABLED "on")
|
||||
else(ENABLED)
|
||||
else()
|
||||
set(ENABLED "off")
|
||||
endif(ENABLED)
|
||||
endif()
|
||||
set(WITH_${PLUGIN}_PLUGIN_INTERNAL ${ENABLED} CACHE INTERNAL "")
|
||||
endmacro(set_enabled_plugin)
|
||||
|
||||
@ -72,7 +37,6 @@ endmacro(disable_plugin)
|
||||
# it used to build examples and tools
|
||||
macro(target_link_qca_libraries TARGET)
|
||||
# Link with QCA library
|
||||
target_link_libraries(${TARGET} ${QT_QTCORE_LIBRARY})
|
||||
target_link_libraries(${TARGET} ${QCA_LIB_NAME})
|
||||
|
||||
# Statically link with all enabled QCA plugins
|
||||
@ -82,15 +46,19 @@ macro(target_link_qca_libraries TARGET)
|
||||
# Check plugin for enabled
|
||||
if(WITH_${PLUGIN}_PLUGIN_INTERNAL)
|
||||
target_link_libraries(${TARGET} qca-${PLUGIN})
|
||||
endif(WITH_${PLUGIN}_PLUGIN_INTERNAL)
|
||||
endif()
|
||||
endforeach(PLUGIN)
|
||||
endif(STATIC_PLUGINS)
|
||||
endif()
|
||||
endmacro(target_link_qca_libraries)
|
||||
|
||||
# it used to build unittests
|
||||
macro(target_link_qca_test_libraries TARGET)
|
||||
target_link_qca_libraries(${TARGET})
|
||||
target_link_libraries(${TARGET} ${QT_QTTEST_LIBRARY})
|
||||
if(QT6)
|
||||
target_link_libraries(${TARGET} Qt6::Test)
|
||||
else()
|
||||
target_link_libraries(${TARGET} Qt5::Test)
|
||||
endif()
|
||||
endmacro(target_link_qca_test_libraries)
|
||||
|
||||
# it used to build unittests
|
||||
@ -109,7 +77,7 @@ macro(install_pdb TARGET INSTALL_PATH)
|
||||
get_target_property(LOCATION ${TARGET} LOCATION_RELWITHDEBINFO)
|
||||
string(REGEX REPLACE "\\.[^.]*$" ".pdb" LOCATION "${LOCATION}")
|
||||
install(FILES ${LOCATION} DESTINATION ${INSTALL_PATH} CONFIGURATIONS RelWithDebInfo)
|
||||
endif(MSVC)
|
||||
endif()
|
||||
endmacro(install_pdb)
|
||||
|
||||
macro(normalize_path PATH)
|
||||
|
@ -4,7 +4,7 @@ cmake_policy(SET CMP0007 OLD)
|
||||
|
||||
if (NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
|
||||
message(FATAL_ERROR "Cannot find install manifest: \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\"")
|
||||
endif(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
|
||||
endif()
|
||||
|
||||
file(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files)
|
||||
string(REGEX REPLACE "\n" ";" files "${files}")
|
||||
@ -19,8 +19,8 @@ foreach (file ${files})
|
||||
)
|
||||
if(NOT ${rm_retval} EQUAL 0)
|
||||
message(FATAL_ERROR "Problem when removing \"$ENV{DESTDIR}${file}\"")
|
||||
endif (NOT ${rm_retval} EQUAL 0)
|
||||
else (EXISTS "$ENV{DESTDIR}${file}")
|
||||
endif()
|
||||
else()
|
||||
message(STATUS "File \"$ENV{DESTDIR}${file}\" does not exist.")
|
||||
endif (EXISTS "$ENV{DESTDIR}${file}")
|
||||
endif()
|
||||
endforeach(file)
|
||||
|
@ -5,11 +5,11 @@ CONFIG *= qt
|
||||
|
||||
LINKAGE =
|
||||
|
||||
exists($$QCA_LIBDIR/qca.framework) {
|
||||
exists($$QCA_LIBDIR/@QCA_LIB_NAME@.framework) {
|
||||
QMAKE_CXXFLAGS += -F$$QCA_LIBDIR
|
||||
LIBS *= -F$$QCA_LIBDIR
|
||||
INCLUDEPATH += $$QCA_LIBDIR/qca.framework/Headers
|
||||
LINKAGE = -framework qca
|
||||
INCLUDEPATH += $$QCA_LIBDIR/@QCA_LIB_NAME@.framework/Headers
|
||||
LINKAGE = -framework @QCA_LIB_NAME@
|
||||
}
|
||||
|
||||
# else, link normally
|
||||
|
3
docs/Doxyfile.local
Normal file
3
docs/Doxyfile.local
Normal file
@ -0,0 +1,3 @@
|
||||
### KApiDox Project-specific Overrides File
|
||||
|
||||
FILE_PATTERNS += *.doco
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
@ -1,5 +1,8 @@
|
||||
if(Qt5Core_FOUND)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Qt5Core_EXECUTABLE_COMPILE_FLAGS}")
|
||||
if(QT6)
|
||||
find_package(Qt6 REQUIRED Network)
|
||||
else()
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Qt5Core_EXECUTABLE_COMPILE_FLAGS}")
|
||||
find_package(Qt5 REQUIRED Network)
|
||||
endif()
|
||||
add_subdirectory(aes-cmac)
|
||||
add_subdirectory(base64test)
|
||||
|
@ -31,156 +31,144 @@
|
||||
|
||||
class AESCMACContext : public QCA::MACContext
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
AESCMACContext(QCA::Provider *p) : QCA::MACContext(p, "cmac(aes)")
|
||||
AESCMACContext(QCA::Provider *p)
|
||||
: QCA::MACContext(p, QStringLiteral("cmac(aes)"))
|
||||
{
|
||||
}
|
||||
|
||||
~AESCMACContext()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
// Helper to left shift an arbitrary length array
|
||||
// This is heavily based on the example in the I-D.
|
||||
QCA::SecureArray leftShift(const QCA::SecureArray &array)
|
||||
{
|
||||
// We create an output of the same size as the input
|
||||
QCA::SecureArray out(array.size());
|
||||
// We handle one byte at a time - this is the high bit
|
||||
// from the previous byte.
|
||||
int overflow = 0;
|
||||
// We create an output of the same size as the input
|
||||
QCA::SecureArray out(array.size());
|
||||
// We handle one byte at a time - this is the high bit
|
||||
// from the previous byte.
|
||||
int overflow = 0;
|
||||
|
||||
// work through each byte.
|
||||
for (int i = array.size() -1; i >= 0; --i) {
|
||||
// do the left shift on this byte.
|
||||
out[i] = array[i] << 1;
|
||||
// make the low bit on this byte be the high bit
|
||||
// from the previous byte.
|
||||
out[i] |= overflow;
|
||||
// save the high bit for next time
|
||||
overflow = (array[i] & 0x80) ? 1 : 0;
|
||||
}
|
||||
return out;
|
||||
// work through each byte.
|
||||
for (int i = array.size() - 1; i >= 0; --i) {
|
||||
// do the left shift on this byte.
|
||||
out[i] = array[i] << 1;
|
||||
// make the low bit on this byte be the high bit
|
||||
// from the previous byte.
|
||||
out[i] |= overflow;
|
||||
// save the high bit for next time
|
||||
overflow = (array[i] & 0x80) ? 1 : 0;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
// Helper to XOR two arrays - must be same length
|
||||
QCA::SecureArray xorArray(const QCA::SecureArray &array1,
|
||||
const QCA::SecureArray &array2)
|
||||
QCA::SecureArray xorArray(const QCA::SecureArray &array1, const QCA::SecureArray &array2)
|
||||
{
|
||||
if (array1.size() != array2.size())
|
||||
// empty array
|
||||
return QCA::SecureArray();
|
||||
if (array1.size() != array2.size())
|
||||
// empty array
|
||||
return QCA::SecureArray();
|
||||
|
||||
QCA::SecureArray result(array1.size());
|
||||
QCA::SecureArray result(array1.size());
|
||||
|
||||
for (int i = 0; i < array1.size(); ++i)
|
||||
result[i] = array1[i] ^ array2[i];
|
||||
for (int i = 0; i < array1.size(); ++i)
|
||||
result[i] = array1[i] ^ array2[i];
|
||||
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void setup(const QCA::SymmetricKey &key)
|
||||
void setup(const QCA::SymmetricKey &key) override
|
||||
{
|
||||
// We might not have a real key, since this can get called
|
||||
// from the constructor.
|
||||
if (key.size() == 0)
|
||||
return;
|
||||
// We might not have a real key, since this can get called
|
||||
// from the constructor.
|
||||
if (key.size() == 0)
|
||||
return;
|
||||
|
||||
m_key = key;
|
||||
// Generate the subkeys
|
||||
QCA::SecureArray const_Zero(16);
|
||||
QCA::SecureArray const_Rb(16);
|
||||
const_Rb[15] = (char)0x87;
|
||||
m_key = key;
|
||||
// Generate the subkeys
|
||||
QCA::SecureArray const_Zero(16);
|
||||
QCA::SecureArray const_Rb(16);
|
||||
const_Rb[15] = (char)0x87;
|
||||
|
||||
m_X = const_Zero;
|
||||
m_residual = QCA::SecureArray();
|
||||
m_X = const_Zero;
|
||||
m_residual = QCA::SecureArray();
|
||||
|
||||
// Figure 2.2, step 1.
|
||||
QCA::Cipher aesObj(QString("aes128"),
|
||||
QCA::Cipher::ECB, QCA::Cipher::DefaultPadding,
|
||||
QCA::Encode, key);
|
||||
QCA::SecureArray L = aesObj.process(const_Zero);
|
||||
// Figure 2.2, step 1.
|
||||
QCA::Cipher aesObj(QStringLiteral("aes128"), QCA::Cipher::ECB, QCA::Cipher::DefaultPadding, QCA::Encode, key);
|
||||
QCA::SecureArray L = aesObj.process(const_Zero);
|
||||
|
||||
// Figure 2.2, step 2
|
||||
if (0 == (L[0] & 0x80))
|
||||
m_k1 = leftShift(L);
|
||||
else
|
||||
m_k1 = xorArray(leftShift(L), const_Rb);
|
||||
// Figure 2.2, step 2
|
||||
if (0 == (L[0] & 0x80))
|
||||
m_k1 = leftShift(L);
|
||||
else
|
||||
m_k1 = xorArray(leftShift(L), const_Rb);
|
||||
|
||||
// Figure 2.2, step 3
|
||||
if (0 == (m_k1[0] & 0x80))
|
||||
m_k2 = leftShift(m_k1);
|
||||
else
|
||||
m_k2 = xorArray(leftShift(m_k1), const_Rb);
|
||||
// Figure 2.2, step 3
|
||||
if (0 == (m_k1[0] & 0x80))
|
||||
m_k2 = leftShift(m_k1);
|
||||
else
|
||||
m_k2 = xorArray(leftShift(m_k1), const_Rb);
|
||||
}
|
||||
|
||||
QCA::Provider::Context *clone() const
|
||||
QCA::Provider::Context *clone() const override
|
||||
{
|
||||
return new AESCMACContext(*this);
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
setup(m_key);
|
||||
setup(m_key);
|
||||
}
|
||||
|
||||
QCA::KeyLength keyLength() const
|
||||
QCA::KeyLength keyLength() const override
|
||||
{
|
||||
return QCA::KeyLength(16, 16, 1);
|
||||
}
|
||||
|
||||
// This is a bit different to the way the I-D does it,
|
||||
// to allow for multiple update() calls.
|
||||
void update(const QCA::MemoryRegion &a)
|
||||
void update(const QCA::MemoryRegion &a) override
|
||||
{
|
||||
QCA::SecureArray bytesToProcess = m_residual + a;
|
||||
int blockNum;
|
||||
// note that we don't want to do the last full block here, because
|
||||
// it needs special treatment in final().
|
||||
for (blockNum = 0; blockNum < ((bytesToProcess.size()-1)/16); ++blockNum) {
|
||||
// copy a block of data
|
||||
QCA::SecureArray thisBlock(16);
|
||||
for (int yalv = 0; yalv < 16; ++yalv)
|
||||
thisBlock[yalv] = bytesToProcess[blockNum*16 + yalv];
|
||||
QCA::SecureArray bytesToProcess = m_residual + a;
|
||||
int blockNum;
|
||||
// note that we don't want to do the last full block here, because
|
||||
// it needs special treatment in final().
|
||||
for (blockNum = 0; blockNum < ((bytesToProcess.size() - 1) / 16); ++blockNum) {
|
||||
// copy a block of data
|
||||
QCA::SecureArray thisBlock(16);
|
||||
for (int yalv = 0; yalv < 16; ++yalv)
|
||||
thisBlock[yalv] = bytesToProcess[blockNum * 16 + yalv];
|
||||
|
||||
m_Y = xorArray(m_X, thisBlock);
|
||||
m_Y = xorArray(m_X, thisBlock);
|
||||
|
||||
QCA::Cipher aesObj(QString("aes128"),
|
||||
QCA::Cipher::ECB, QCA::Cipher::DefaultPadding,
|
||||
QCA::Encode, m_key);
|
||||
m_X = aesObj.process(m_Y);
|
||||
}
|
||||
// This can be between 1 and 16
|
||||
int numBytesLeft = bytesToProcess.size() - 16*blockNum;
|
||||
// we copy the left over part
|
||||
m_residual.resize(numBytesLeft);
|
||||
for(int yalv = 0; yalv < numBytesLeft; ++yalv)
|
||||
m_residual[yalv] = bytesToProcess[blockNum*16 + yalv];
|
||||
QCA::Cipher aesObj(
|
||||
QStringLiteral("aes128"), QCA::Cipher::ECB, QCA::Cipher::DefaultPadding, QCA::Encode, m_key);
|
||||
m_X = aesObj.process(m_Y);
|
||||
}
|
||||
// This can be between 1 and 16
|
||||
int numBytesLeft = bytesToProcess.size() - 16 * blockNum;
|
||||
// we copy the left over part
|
||||
m_residual.resize(numBytesLeft);
|
||||
for (int yalv = 0; yalv < numBytesLeft; ++yalv)
|
||||
m_residual[yalv] = bytesToProcess[blockNum * 16 + yalv];
|
||||
}
|
||||
|
||||
void final( QCA::MemoryRegion *out)
|
||||
void final(QCA::MemoryRegion *out) override
|
||||
{
|
||||
QCA::SecureArray lastBlock;
|
||||
int numBytesLeft = m_residual.size();
|
||||
|
||||
if ( numBytesLeft != 16 ) {
|
||||
// no full block, so we have to pad.
|
||||
m_residual.resize(16);
|
||||
m_residual[numBytesLeft] = (char)0x80;
|
||||
lastBlock = xorArray(m_residual, m_k2);
|
||||
} else {
|
||||
// this is a full block - no padding
|
||||
lastBlock = xorArray(m_residual, m_k1);
|
||||
}
|
||||
m_Y = xorArray(m_X, lastBlock);
|
||||
QCA::Cipher aesObj(QString("aes128"),
|
||||
QCA::Cipher::ECB, QCA::Cipher::DefaultPadding,
|
||||
QCA::Encode, m_key);
|
||||
*out = aesObj.process(m_Y);
|
||||
QCA::SecureArray lastBlock;
|
||||
int numBytesLeft = m_residual.size();
|
||||
|
||||
if (numBytesLeft != 16) {
|
||||
// no full block, so we have to pad.
|
||||
m_residual.resize(16);
|
||||
m_residual[numBytesLeft] = (char)0x80;
|
||||
lastBlock = xorArray(m_residual, m_k2);
|
||||
} else {
|
||||
// this is a full block - no padding
|
||||
lastBlock = xorArray(m_residual, m_k1);
|
||||
}
|
||||
m_Y = xorArray(m_X, lastBlock);
|
||||
QCA::Cipher aesObj(QStringLiteral("aes128"), QCA::Cipher::ECB, QCA::Cipher::DefaultPadding, QCA::Encode, m_key);
|
||||
*out = aesObj.process(m_Y);
|
||||
}
|
||||
|
||||
protected:
|
||||
@ -202,49 +190,47 @@ protected:
|
||||
class ClientSideProvider : public QCA::Provider
|
||||
{
|
||||
public:
|
||||
int qcaVersion() const
|
||||
{
|
||||
return QCA_VERSION;
|
||||
}
|
||||
int qcaVersion() const override
|
||||
{
|
||||
return QCA_VERSION;
|
||||
}
|
||||
|
||||
QString name() const
|
||||
{
|
||||
return "exampleClientSideProvider";
|
||||
}
|
||||
QString name() const override
|
||||
{
|
||||
return QStringLiteral("exampleClientSideProvider");
|
||||
}
|
||||
|
||||
QStringList features() const
|
||||
{
|
||||
QStringList list;
|
||||
list += "cmac(aes)";
|
||||
// you can add more features in here, if you have some.
|
||||
return list;
|
||||
}
|
||||
QStringList features() const override
|
||||
{
|
||||
QStringList list;
|
||||
list += QStringLiteral("cmac(aes)");
|
||||
// you can add more features in here, if you have some.
|
||||
return list;
|
||||
}
|
||||
|
||||
Provider::Context *createContext(const QString &type)
|
||||
{
|
||||
if(type == "cmac(aes)")
|
||||
return new AESCMACContext(this);
|
||||
// else if (type == some other feature)
|
||||
// return some other context.
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
Provider::Context *createContext(const QString &type) override
|
||||
{
|
||||
if (type == QLatin1String("cmac(aes)"))
|
||||
return new AESCMACContext(this);
|
||||
// else if (type == some other feature)
|
||||
// return some other context.
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// AES CMAC is a Message Authentication Code based on a block cipher
|
||||
// instead of the more normal keyed hash.
|
||||
// See RFC 4493 "The AES-CMAC Algorithm"
|
||||
class AES_CMAC: public QCA::MessageAuthenticationCode
|
||||
class AES_CMAC : public QCA::MessageAuthenticationCode
|
||||
{
|
||||
public:
|
||||
AES_CMAC(const QCA::SymmetricKey &key = QCA::SymmetricKey(),
|
||||
const QString &provider = QString()):
|
||||
QCA::MessageAuthenticationCode( "cmac(aes)", key, provider)
|
||||
{}
|
||||
AES_CMAC(const QCA::SymmetricKey &key = QCA::SymmetricKey(), const QString &provider = QString())
|
||||
: QCA::MessageAuthenticationCode(QStringLiteral("cmac(aes)"), key, provider)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
// the Initializer object sets things up, and
|
||||
@ -255,64 +241,66 @@ int main(int argc, char **argv)
|
||||
|
||||
QCoreApplication app(argc, argv);
|
||||
|
||||
if( ! QCA::isSupported("aes128-ecb") ) {
|
||||
qDebug() << "AES not supported!";
|
||||
if (!QCA::isSupported("aes128-ecb")) {
|
||||
qDebug() << "AES not supported!";
|
||||
}
|
||||
|
||||
if ( QCA::insertProvider(new ClientSideProvider, 0) )
|
||||
qDebug() << "Inserted our provider";
|
||||
if (QCA::insertProvider(new ClientSideProvider, 0))
|
||||
qDebug() << "Inserted our provider";
|
||||
else
|
||||
qDebug() << "our provider could not be added";
|
||||
qDebug() << "our provider could not be added";
|
||||
|
||||
// We should check AES CMAC is supported before using it.
|
||||
if( ! QCA::isSupported("cmac(aes)") ) {
|
||||
qDebug() << "AES CMAC not supported!";
|
||||
if (!QCA::isSupported("cmac(aes)")) {
|
||||
qDebug() << "AES CMAC not supported!";
|
||||
} else {
|
||||
// create the required object
|
||||
AES_CMAC cmacObject;
|
||||
// create the required object
|
||||
AES_CMAC cmacObject;
|
||||
|
||||
// create the key
|
||||
QCA::SymmetricKey key(QCA::hexToArray("2b7e151628aed2a6abf7158809cf4f3c"));
|
||||
// create the key
|
||||
QCA::SymmetricKey key(QCA::hexToArray(QStringLiteral("2b7e151628aed2a6abf7158809cf4f3c")));
|
||||
|
||||
// set the MAC to use the key
|
||||
cmacObject.setup(key);
|
||||
// set the MAC to use the key
|
||||
cmacObject.setup(key);
|
||||
|
||||
QCA::SecureArray message = QCA::hexToArray("6bc1bee22e409f96e93d7e117393172a"
|
||||
"ae2d8a571e03ac9c9eb76fac45af8e51"
|
||||
"30c81c46a35ce411e5fbc1191a0a52ef"
|
||||
"f69f2445df4f9b17ad2b417be66c3710");
|
||||
QCA::SecureArray message1(message);
|
||||
message1.resize(0);
|
||||
qDebug();
|
||||
qDebug() << "Message1: " << QCA::arrayToHex(message1.toByteArray());
|
||||
qDebug() << "Expecting: bb1d6929e95937287fa37d129b756746";
|
||||
qDebug() << "AES-CMAC: " << QCA::arrayToHex(cmacObject.process(message1).toByteArray());
|
||||
QCA::SecureArray message =
|
||||
QCA::hexToArray(QStringLiteral("6bc1bee22e409f96e93d7e117393172a"
|
||||
"ae2d8a571e03ac9c9eb76fac45af8e51"
|
||||
"30c81c46a35ce411e5fbc1191a0a52ef"
|
||||
"f69f2445df4f9b17ad2b417be66c3710"));
|
||||
QCA::SecureArray message1(message);
|
||||
message1.resize(0);
|
||||
qDebug();
|
||||
qDebug() << "Message1: " << QCA::arrayToHex(message1.toByteArray());
|
||||
qDebug() << "Expecting: bb1d6929e95937287fa37d129b756746";
|
||||
qDebug() << "AES-CMAC: " << QCA::arrayToHex(cmacObject.process(message1).toByteArray());
|
||||
|
||||
cmacObject.clear();
|
||||
QCA::SecureArray message2(message);
|
||||
message2.resize(16);
|
||||
qDebug();
|
||||
qDebug() << "Message2: " << QCA::arrayToHex(message2.toByteArray());
|
||||
qDebug() << "Expecting: 070a16b46b4d4144f79bdd9dd04a287c";
|
||||
qDebug() << "AES-CMAC: " << QCA::arrayToHex(cmacObject.process(message2).toByteArray());
|
||||
cmacObject.clear();
|
||||
QCA::SecureArray message2(message);
|
||||
message2.resize(16);
|
||||
qDebug();
|
||||
qDebug() << "Message2: " << QCA::arrayToHex(message2.toByteArray());
|
||||
qDebug() << "Expecting: 070a16b46b4d4144f79bdd9dd04a287c";
|
||||
qDebug() << "AES-CMAC: " << QCA::arrayToHex(cmacObject.process(message2).toByteArray());
|
||||
|
||||
cmacObject.clear();
|
||||
QCA::SecureArray message3(message);
|
||||
message3.resize(40);
|
||||
qDebug();
|
||||
qDebug() << "Message3: " << QCA::arrayToHex(message3.toByteArray());
|
||||
qDebug() << "Expecting: dfa66747de9ae63030ca32611497c827";
|
||||
qDebug() << "AES-CMAC " << QCA::arrayToHex(cmacObject.process(message3).toByteArray());
|
||||
cmacObject.clear();
|
||||
QCA::SecureArray message3(message);
|
||||
message3.resize(40);
|
||||
qDebug();
|
||||
qDebug() << "Message3: " << QCA::arrayToHex(message3.toByteArray());
|
||||
qDebug() << "Expecting: dfa66747de9ae63030ca32611497c827";
|
||||
qDebug() << "AES-CMAC " << QCA::arrayToHex(cmacObject.process(message3).toByteArray());
|
||||
|
||||
cmacObject.clear();
|
||||
QCA::SecureArray message4(message);
|
||||
message4.resize(64);
|
||||
qDebug();
|
||||
qDebug() << "Message4: " << QCA::arrayToHex(message4.toByteArray());
|
||||
qDebug() << "Expecting: 51f0bebf7e3b9d92fc49741779363cfe";
|
||||
qDebug() << "AES-CMAC: " << QCA::arrayToHex(cmacObject.process(message4).toByteArray());
|
||||
cmacObject.clear();
|
||||
QCA::SecureArray message4(message);
|
||||
message4.resize(64);
|
||||
qDebug();
|
||||
qDebug() << "Message4: " << QCA::arrayToHex(message4.toByteArray());
|
||||
qDebug() << "Expecting: 51f0bebf7e3b9d92fc49741779363cfe";
|
||||
qDebug() << "AES-CMAC: " << QCA::arrayToHex(cmacObject.process(message4).toByteArray());
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include "aes-cmac.moc"
|
||||
|
@ -32,40 +32,39 @@
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
QCoreApplication(argc, argv);
|
||||
QCoreApplication(argc, argv);
|
||||
|
||||
// the Initializer object sets things up, and
|
||||
// also does cleanup when it goes out of scope
|
||||
QCA::Initializer init;
|
||||
// the Initializer object sets things up, and
|
||||
// also does cleanup when it goes out of scope
|
||||
QCA::Initializer init;
|
||||
|
||||
// we use the first argument as the data to encode
|
||||
// if an argument is provided. Use "hello" if no argument
|
||||
QByteArray arg; // empty array
|
||||
arg.append((argc >= 2) ? argv[1] : "hello");
|
||||
// we use the first argument as the data to encode
|
||||
// if an argument is provided. Use "hello" if no argument
|
||||
QByteArray arg; // empty array
|
||||
arg.append((argc >= 2) ? argv[1] : "hello");
|
||||
|
||||
// create our object, which does encoding by default
|
||||
// QCA::Base64 encoder(QCA::Encode); is equivalent
|
||||
QCA::Base64 encoder;
|
||||
// create our object, which does encoding by default
|
||||
// QCA::Base64 encoder(QCA::Encode); is equivalent
|
||||
QCA::Base64 encoder;
|
||||
|
||||
// This does the actual conversion (encoding).
|
||||
// You might prefer to use encoder.encode(); and have
|
||||
// it return a QCA::SecureArray, depending on your needs
|
||||
QString encoded = encoder.arrayToString(arg);
|
||||
// This does the actual conversion (encoding).
|
||||
// You might prefer to use encoder.encode(); and have
|
||||
// it return a QCA::SecureArray, depending on your needs
|
||||
QString encoded = encoder.arrayToString(arg);
|
||||
|
||||
std::cout << arg.data() << " in base64 encoding is ";
|
||||
std::cout << encoded.toLatin1().data() << std::endl;
|
||||
std::cout << arg.data() << " in base64 encoding is ";
|
||||
std::cout << encoded.toLatin1().data() << std::endl;
|
||||
|
||||
// This time, we'll create an object to decode base64. We
|
||||
// could also have reused the existing object, calling
|
||||
// clear(); and setup(QCA::Decode); on it.
|
||||
QCA::Base64 decoder(QCA::Decode);
|
||||
// This time, we'll create an object to decode base64. We
|
||||
// could also have reused the existing object, calling
|
||||
// clear(); and setup(QCA::Decode); on it.
|
||||
QCA::Base64 decoder(QCA::Decode);
|
||||
|
||||
// This time, we convert a QString into a QString
|
||||
QString decoded = decoder.decodeString(encoded);
|
||||
// This time, we convert a QString into a QString
|
||||
QString decoded = decoder.decodeString(encoded);
|
||||
|
||||
std::cout << encoded.toLatin1().data() << " decoded from base64 is ";
|
||||
std::cout << decoded.toLatin1().data() << std::endl;
|
||||
std::cout << encoded.toLatin1().data() << " decoded from base64 is ";
|
||||
std::cout << decoded.toLatin1().data() << std::endl;
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -20,10 +20,10 @@
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
#include <QtCrypto>
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QFile>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
@ -34,7 +34,7 @@
|
||||
// dump out information about some part of the certificate
|
||||
// we use this same approach for information about the subject
|
||||
// of the certificate, and also about the issuer of the certificate
|
||||
static void dumpCertificateInfo( QCA::CertificateInfo info)
|
||||
static void dumpCertificateInfo(const QCA::CertificateInfo &info)
|
||||
{
|
||||
std::cout << " Organization: " << std::endl;
|
||||
|
||||
@ -48,37 +48,35 @@ static void dumpCertificateInfo( QCA::CertificateInfo info)
|
||||
// out each value. Note that is uncommon for a certificate to
|
||||
// actually contain multiple values for a single parameter.
|
||||
QString organization;
|
||||
foreach( organization, orgInfoList ) {
|
||||
std::cout << " " << qPrintable(organization) << std::endl;
|
||||
foreach (organization, orgInfoList) {
|
||||
std::cout << " " << qPrintable(organization) << std::endl;
|
||||
}
|
||||
|
||||
std::cout << " Country: " << std::endl;
|
||||
// As above, however this shows a more compact way to represent
|
||||
// the iteration and output.
|
||||
foreach( QString country, info.values(QCA::Country) ) {
|
||||
std::cout << " " << qPrintable(country) << std::endl;
|
||||
foreach (QString country, info.values(QCA::Country)) { // clazy:exclude=container-anti-pattern
|
||||
std::cout << " " << qPrintable(country) << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
// This is just a convenience routine
|
||||
static void dumpSubjectInfo( QCA::CertificateInfo subject)
|
||||
static void dumpSubjectInfo(const QCA::CertificateInfo &subject)
|
||||
{
|
||||
std::cout << "Subject: " << std::endl;
|
||||
|
||||
dumpCertificateInfo( subject );
|
||||
dumpCertificateInfo(subject);
|
||||
}
|
||||
|
||||
|
||||
// This is just a convenience routine
|
||||
static void dumpIssuerInfo( QCA::CertificateInfo issuer)
|
||||
static void dumpIssuerInfo(const QCA::CertificateInfo &issuer)
|
||||
{
|
||||
std::cout << "Issuer: " << std::endl;
|
||||
|
||||
dumpCertificateInfo( issuer );
|
||||
dumpCertificateInfo(issuer);
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char** argv)
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
// the Initializer object sets things up, and
|
||||
// also does cleanup when it goes out of scope
|
||||
@ -87,9 +85,9 @@ int main(int argc, char** argv)
|
||||
QCoreApplication app(argc, argv);
|
||||
|
||||
// We need to ensure that we have certificate handling support
|
||||
if ( !QCA::isSupported( "cert" ) ) {
|
||||
std::cout << "Sorry, no PKI certificate support" << std::endl;
|
||||
return 1;
|
||||
if (!QCA::isSupported("cert")) {
|
||||
std::cout << "Sorry, no PKI certificate support" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// We are going to work with a number of certificates, and a
|
||||
@ -100,77 +98,76 @@ int main(int argc, char** argv)
|
||||
// as a filename to read the keys from. If there is no argument, we just
|
||||
// read from the system store certificates.
|
||||
if (argc >= 2) {
|
||||
// we are going to read the certificates in using a single call
|
||||
// which requires a CertificateCollection.
|
||||
QCA::CertificateCollection filecerts;
|
||||
// The conversion can be tested (although you don't have to) to find out if it
|
||||
// worked.
|
||||
QCA::ConvertResult importResult;
|
||||
// This imports all the PEM encoded certificates from the file specified as the argument
|
||||
// Note that you pass in a pointer to the result argument.
|
||||
filecerts = QCA::CertificateCollection::fromFlatTextFile( argv[1], &importResult );
|
||||
if ( QCA::ConvertGood == importResult) {
|
||||
std::cout << "Import succeeded" << std::endl;
|
||||
// this turns the CertificateCollection into a QList of Certificate objects
|
||||
certlist = filecerts.certificates();
|
||||
}
|
||||
// we are going to read the certificates in using a single call
|
||||
// which requires a CertificateCollection.
|
||||
QCA::CertificateCollection filecerts;
|
||||
// The conversion can be tested (although you don't have to) to find out if it
|
||||
// worked.
|
||||
QCA::ConvertResult importResult;
|
||||
// This imports all the PEM encoded certificates from the file specified as the argument
|
||||
// Note that you pass in a pointer to the result argument.
|
||||
filecerts = QCA::CertificateCollection::fromFlatTextFile(QFile::decodeName(argv[1]), &importResult);
|
||||
if (QCA::ConvertGood == importResult) {
|
||||
std::cout << "Import succeeded" << std::endl;
|
||||
// this turns the CertificateCollection into a QList of Certificate objects
|
||||
certlist = filecerts.certificates();
|
||||
}
|
||||
} else {
|
||||
// we have no arguments, so just use the system certificates
|
||||
if ( !QCA::haveSystemStore() ) {
|
||||
std::cout << "System certificates not available" << std::endl;
|
||||
return 2;
|
||||
}
|
||||
// we have no arguments, so just use the system certificates
|
||||
if (!QCA::haveSystemStore()) {
|
||||
std::cout << "System certificates not available" << std::endl;
|
||||
return 2;
|
||||
}
|
||||
|
||||
// Similar to above, except we just want the system certificates
|
||||
QCA::CertificateCollection systemcerts = QCA::systemStore();
|
||||
// Similar to above, except we just want the system certificates
|
||||
QCA::CertificateCollection systemcerts = QCA::systemStore();
|
||||
|
||||
// this turns the CertificateCollection into a QList of Certificate objects
|
||||
certlist = systemcerts.certificates();
|
||||
// this turns the CertificateCollection into a QList of Certificate objects
|
||||
certlist = systemcerts.certificates();
|
||||
}
|
||||
|
||||
std::cout << "Number of certificates: " << certlist.count() << std::endl;
|
||||
|
||||
QCA::Certificate cert;
|
||||
foreach (cert, certlist) {
|
||||
std::cout << "Serial Number:";
|
||||
// the serial number of the certificate is a QCA::BigInteger, but we can
|
||||
// just convert it to a string, and then output it.
|
||||
std::cout << qPrintable(cert.serialNumber().toString()) << std::endl;
|
||||
std::cout << "Serial Number:";
|
||||
// the serial number of the certificate is a QCA::BigInteger, but we can
|
||||
// just convert it to a string, and then output it.
|
||||
std::cout << qPrintable(cert.serialNumber().toString()) << std::endl;
|
||||
|
||||
// The subject information shows properties of who the certificate
|
||||
// applies to. See the convenience routines above.
|
||||
dumpSubjectInfo( cert.subjectInfo() );
|
||||
// The subject information shows properties of who the certificate
|
||||
// applies to. See the convenience routines above.
|
||||
dumpSubjectInfo(cert.subjectInfo());
|
||||
|
||||
// The issuer information shows properties of who the certificate
|
||||
// was signed by. See the convenience routines above.
|
||||
dumpIssuerInfo( cert.issuerInfo() );
|
||||
// The issuer information shows properties of who the certificate
|
||||
// was signed by. See the convenience routines above.
|
||||
dumpIssuerInfo(cert.issuerInfo());
|
||||
|
||||
// Test if the certificate can be used as a certificate authority
|
||||
if ( cert.isCA() ) {
|
||||
std::cout << "Is certificate authority" << std::endl;
|
||||
} else {
|
||||
std::cout << "Is not a certificate authority" << std::endl;
|
||||
}
|
||||
// Test if the certificate can be used as a certificate authority
|
||||
if (cert.isCA()) {
|
||||
std::cout << "Is certificate authority" << std::endl;
|
||||
} else {
|
||||
std::cout << "Is not a certificate authority" << std::endl;
|
||||
}
|
||||
|
||||
// Test if the certificate is self-signed.
|
||||
if (cert.isSelfSigned() ) {
|
||||
std::cout << "Self signed" << std::endl;
|
||||
} else {
|
||||
std::cout << "Is not self-signed!!!" << std::endl;
|
||||
}
|
||||
// Test if the certificate is self-signed.
|
||||
if (cert.isSelfSigned()) {
|
||||
std::cout << "Self signed" << std::endl;
|
||||
} else {
|
||||
std::cout << "Is not self-signed!!!" << std::endl;
|
||||
}
|
||||
|
||||
// Certificate are only valid between specific dates. We can get the dates
|
||||
// (as a QDateTime) using a couple of calls
|
||||
std::cout << "Valid from " << qPrintable(cert.notValidBefore().toString());
|
||||
std::cout << ", until " << qPrintable(cert.notValidAfter().toString());
|
||||
std::cout << std::endl;
|
||||
// Certificate are only valid between specific dates. We can get the dates
|
||||
// (as a QDateTime) using a couple of calls
|
||||
std::cout << "Valid from " << qPrintable(cert.notValidBefore().toString());
|
||||
std::cout << ", until " << qPrintable(cert.notValidAfter().toString());
|
||||
std::cout << std::endl;
|
||||
|
||||
// You can get the certificate in PEM encoding with a simple toPEM() call
|
||||
std::cout << "PEM:" << std::endl;
|
||||
std::cout << qPrintable(cert.toPEM());
|
||||
std::cout << std::endl << std::endl;
|
||||
}
|
||||
// You can get the certificate in PEM encoding with a simple toPEM() call
|
||||
std::cout << "PEM:" << std::endl;
|
||||
std::cout << qPrintable(cert.toPEM());
|
||||
std::cout << std::endl << std::endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -22,7 +22,7 @@
|
||||
|
||||
// QtCrypto has the declarations for all of QCA
|
||||
#include <QtCrypto>
|
||||
#include <stdio.h>
|
||||
#include <cstdio>
|
||||
|
||||
#include <QCoreApplication>
|
||||
|
||||
@ -43,91 +43,88 @@ int main(int argc, char **argv)
|
||||
QCA::SecureArray arg = (argc >= 2) ? argv[1] : "hello";
|
||||
|
||||
// AES128 testing
|
||||
if(!QCA::isSupported("aes128-cbc-pkcs7"))
|
||||
printf("AES128-CBC not supported!\n");
|
||||
if (!QCA::isSupported("aes128-cbc-pkcs7"))
|
||||
printf("AES128-CBC not supported!\n");
|
||||
else {
|
||||
// Create a random key - you'd probably use one from another
|
||||
// source in a real application
|
||||
QCA::SymmetricKey key(16);
|
||||
// Create a random key - you'd probably use one from another
|
||||
// source in a real application
|
||||
QCA::SymmetricKey key(16);
|
||||
|
||||
// Create a random initialisation vector - you need this
|
||||
// value to decrypt the resulting cipher text, but it
|
||||
// need not be kept secret (unlike the key).
|
||||
QCA::InitializationVector iv(16);
|
||||
// Create a random initialisation vector - you need this
|
||||
// value to decrypt the resulting cipher text, but it
|
||||
// need not be kept secret (unlike the key).
|
||||
QCA::InitializationVector iv(16);
|
||||
|
||||
// create a 128 bit AES cipher object using Cipher Block Chaining (CBC) mode
|
||||
QCA::Cipher cipher(QString("aes128"),QCA::Cipher::CBC,
|
||||
// use Default padding, which is equivalent to PKCS7 for CBC
|
||||
QCA::Cipher::DefaultPadding,
|
||||
// this object will encrypt
|
||||
QCA::Encode,
|
||||
key, iv);
|
||||
// create a 128 bit AES cipher object using Cipher Block Chaining (CBC) mode
|
||||
QCA::Cipher cipher(QStringLiteral("aes128"),
|
||||
QCA::Cipher::CBC,
|
||||
// use Default padding, which is equivalent to PKCS7 for CBC
|
||||
QCA::Cipher::DefaultPadding,
|
||||
// this object will encrypt
|
||||
QCA::Encode,
|
||||
key,
|
||||
iv);
|
||||
|
||||
// we use the cipher object to encrypt the argument we passed in
|
||||
// the result of that is returned - note that if there is less than
|
||||
// 16 bytes (1 block), then nothing will be returned - it is buffered
|
||||
// update() can be called as many times as required.
|
||||
QCA::SecureArray u = cipher.update(arg);
|
||||
// we use the cipher object to encrypt the argument we passed in
|
||||
// the result of that is returned - note that if there is less than
|
||||
// 16 bytes (1 block), then nothing will be returned - it is buffered
|
||||
// update() can be called as many times as required.
|
||||
QCA::SecureArray u = cipher.update(arg);
|
||||
|
||||
// We need to check if that update() call worked.
|
||||
if (!cipher.ok()) {
|
||||
printf("Update failed\n");
|
||||
}
|
||||
// output the results of that stage
|
||||
printf("AES128 encryption of %s is [%s]\n",
|
||||
arg.data(),
|
||||
qPrintable(QCA::arrayToHex(u.toByteArray())) );
|
||||
// We need to check if that update() call worked.
|
||||
if (!cipher.ok()) {
|
||||
printf("Update failed\n");
|
||||
}
|
||||
// output the results of that stage
|
||||
printf("AES128 encryption of %s is [%s]\n", arg.data(), qPrintable(QCA::arrayToHex(u.toByteArray())));
|
||||
|
||||
// Because we are using PKCS7 padding, we need to output the final (padded) block
|
||||
// Note that we should always call final() even with no padding, to clean up
|
||||
QCA::SecureArray f = cipher.final();
|
||||
|
||||
// Because we are using PKCS7 padding, we need to output the final (padded) block
|
||||
// Note that we should always call final() even with no padding, to clean up
|
||||
QCA::SecureArray f = cipher.final();
|
||||
// Check if the final() call worked
|
||||
if (!cipher.ok()) {
|
||||
printf("Final failed\n");
|
||||
}
|
||||
// and output the resulting block. The ciphertext is the results of update()
|
||||
// and the result of final()
|
||||
printf("Final block for AES128 encryption is [0x%s]\n", qPrintable(QCA::arrayToHex(f.toByteArray())));
|
||||
|
||||
// Check if the final() call worked
|
||||
if (!cipher.ok()) {
|
||||
printf("Final failed\n");
|
||||
}
|
||||
// and output the resulting block. The ciphertext is the results of update()
|
||||
// and the result of final()
|
||||
printf("Final block for AES128 encryption is [0x%s]\n", qPrintable(QCA::arrayToHex(f.toByteArray())) );
|
||||
// re-use the Cipher t decrypt. We need to use the same key and
|
||||
// initialisation vector as in the encryption.
|
||||
cipher.setup(QCA::Decode, key, iv);
|
||||
|
||||
// re-use the Cipher t decrypt. We need to use the same key and
|
||||
// initialisation vector as in the encryption.
|
||||
cipher.setup( QCA::Decode, key, iv );
|
||||
// Build a single cipher text array. You could also call update() with
|
||||
// each block as you receive it, if that is more useful.
|
||||
QCA::SecureArray cipherText = u.append(f);
|
||||
|
||||
// Build a single cipher text array. You could also call update() with
|
||||
// each block as you receive it, if that is more useful.
|
||||
QCA::SecureArray cipherText = u.append(f);
|
||||
// take that cipher text, and decrypt it
|
||||
QCA::SecureArray plainText = cipher.update(cipherText);
|
||||
|
||||
// take that cipher text, and decrypt it
|
||||
QCA::SecureArray plainText = cipher.update(cipherText);
|
||||
// check if the update() call worked
|
||||
if (!cipher.ok()) {
|
||||
printf("Update failed\n");
|
||||
}
|
||||
|
||||
// check if the update() call worked
|
||||
if (!cipher.ok()) {
|
||||
printf("Update failed\n");
|
||||
}
|
||||
// output results
|
||||
printf("Decryption using AES128 of [0x%s] is %s\n",
|
||||
qPrintable(QCA::arrayToHex(cipherText.toByteArray())),
|
||||
plainText.data());
|
||||
|
||||
// output results
|
||||
printf("Decryption using AES128 of [0x%s] is %s\n",
|
||||
qPrintable(QCA::arrayToHex(cipherText.toByteArray())), plainText.data());
|
||||
// Again we need to call final(), to get the last block (with its padding removed)
|
||||
plainText = cipher.final();
|
||||
|
||||
// Again we need to call final(), to get the last block (with its padding removed)
|
||||
plainText = cipher.final();
|
||||
|
||||
// check if the final() call worked
|
||||
if (!cipher.ok()) {
|
||||
printf("Final failed\n");
|
||||
}
|
||||
|
||||
// output results
|
||||
printf("Final decryption block using AES128 is %s\n", plainText.data());
|
||||
// instead of update() and final(), you can do the whole thing
|
||||
// in one step, using process()
|
||||
printf("One step decryption using AES128: %s\n",
|
||||
QCA::SecureArray(cipher.process(cipherText)).data() );
|
||||
// check if the final() call worked
|
||||
if (!cipher.ok()) {
|
||||
printf("Final failed\n");
|
||||
}
|
||||
|
||||
// output results
|
||||
printf("Final decryption block using AES128 is %s\n", plainText.data());
|
||||
// instead of update() and final(), you can do the whole thing
|
||||
// in one step, using process()
|
||||
printf("One step decryption using AES128: %s\n", QCA::SecureArray(cipher.process(cipherText)).data());
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -20,7 +20,6 @@
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
#include <QtCrypto>
|
||||
|
||||
#include <QCoreApplication>
|
||||
@ -30,7 +29,7 @@
|
||||
#include "import_plugins.h"
|
||||
#endif
|
||||
|
||||
int main(int argc, char** argv)
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
// the Initializer object sets things up, and
|
||||
// also does cleanup when it goes out of scope
|
||||
@ -39,31 +38,31 @@ int main(int argc, char** argv)
|
||||
QCoreApplication app(argc, argv);
|
||||
|
||||
// We need to ensure that we have certificate handling support
|
||||
if ( !QCA::isSupported( "cert" ) ) {
|
||||
qWarning() << "Sorry, no PKI certificate support";
|
||||
return 1;
|
||||
if (!QCA::isSupported("cert")) {
|
||||
qWarning() << "Sorry, no PKI certificate support";
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Read in a public key cert
|
||||
// you could also build this using the fromPEMFile() method
|
||||
QCA::Certificate pubCert( "User.pem" );
|
||||
if ( pubCert.isNull() ) {
|
||||
qWarning() << "Sorry, could not import public key certificate";
|
||||
return 1;
|
||||
QCA::Certificate pubCert(QStringLiteral("User.pem"));
|
||||
if (pubCert.isNull()) {
|
||||
qWarning() << "Sorry, could not import public key certificate";
|
||||
return 1;
|
||||
}
|
||||
// We are building the certificate into a SecureMessageKey object, via a
|
||||
// CertificateChain
|
||||
QCA::SecureMessageKey secMsgKey;
|
||||
QCA::CertificateChain chain;
|
||||
chain += pubCert;
|
||||
secMsgKey.setX509CertificateChain( chain );
|
||||
secMsgKey.setX509CertificateChain(chain);
|
||||
|
||||
// build up a SecureMessage object, based on our public key certificate
|
||||
if ( !QCA::isSupported( "cms" ) ) {
|
||||
qWarning() << "Sorry, no CMS support";
|
||||
return 1;
|
||||
if (!QCA::isSupported("cms")) {
|
||||
qWarning() << "Sorry, no CMS support";
|
||||
return 1;
|
||||
}
|
||||
QCA::CMS cms;
|
||||
QCA::CMS cms;
|
||||
QCA::SecureMessage msg(&cms);
|
||||
msg.setRecipient(secMsgKey);
|
||||
|
||||
@ -78,35 +77,34 @@ int main(int argc, char** argv)
|
||||
msg.waitForFinished(1000);
|
||||
|
||||
// check to see if it worked
|
||||
if(!msg.success())
|
||||
{
|
||||
qWarning() << "Error encrypting: " << msg.errorCode();
|
||||
return 1;
|
||||
if (!msg.success()) {
|
||||
qWarning() << "Error encrypting: " << msg.errorCode();
|
||||
return 1;
|
||||
}
|
||||
|
||||
// get the result
|
||||
QByteArray cipherText = msg.read();
|
||||
QByteArray cipherText = msg.read();
|
||||
QCA::Base64 enc;
|
||||
qDebug() << "'" << plainText.data() << "' encrypts to (in base 64): ";
|
||||
qDebug() << enc.arrayToString( cipherText );
|
||||
qDebug() << enc.arrayToString(cipherText);
|
||||
qDebug() << "Message uses" << msg.hashName() << "hashing algorithm";
|
||||
qDebug();
|
||||
|
||||
// Show we can decrypt it with the private key
|
||||
|
||||
// Read in a private key
|
||||
QCA::PrivateKey privKey;
|
||||
QCA::PrivateKey privKey;
|
||||
QCA::ConvertResult convRes;
|
||||
QCA::SecureArray passPhrase = "start";
|
||||
privKey = QCA::PrivateKey::fromPEMFile( "Userkey.pem", passPhrase, &convRes );
|
||||
if ( convRes != QCA::ConvertGood ) {
|
||||
qWarning() << "Sorry, could not import Private Key";
|
||||
return 1;
|
||||
QCA::SecureArray passPhrase = "start";
|
||||
privKey = QCA::PrivateKey::fromPEMFile(QStringLiteral("Userkey.pem"), passPhrase, &convRes);
|
||||
if (convRes != QCA::ConvertGood) {
|
||||
qWarning() << "Sorry, could not import Private Key";
|
||||
return 1;
|
||||
}
|
||||
|
||||
QCA::SecureMessageKey secMsgKey2;
|
||||
// needed?
|
||||
secMsgKey2.setX509CertificateChain( chain );
|
||||
secMsgKey2.setX509CertificateChain(chain);
|
||||
secMsgKey2.setX509PrivateKey(privKey);
|
||||
QCA::SecureMessageKeyList privKeyList;
|
||||
privKeyList += secMsgKey2;
|
||||
@ -116,35 +114,31 @@ int main(int argc, char** argv)
|
||||
// this example simulates encryption and one end, and decryption
|
||||
// at the other
|
||||
QCA::CMS anotherCms;
|
||||
anotherCms.setPrivateKeys( privKeyList );
|
||||
anotherCms.setPrivateKeys(privKeyList);
|
||||
|
||||
QCA::SecureMessage msg2( &anotherCms );
|
||||
QCA::SecureMessage msg2(&anotherCms);
|
||||
|
||||
msg2.startDecrypt();
|
||||
msg2.update( cipherText );
|
||||
msg2.update(cipherText);
|
||||
msg2.end();
|
||||
|
||||
// I think it is reasonable to wait for 1 second for this
|
||||
msg2.waitForFinished(1000);
|
||||
|
||||
// check to see if it worked
|
||||
if(!msg2.success())
|
||||
{
|
||||
qWarning() << "Error encrypting: " << msg2.errorCode();
|
||||
return 1;
|
||||
if (!msg2.success()) {
|
||||
qWarning() << "Error encrypting: " << msg2.errorCode();
|
||||
return 1;
|
||||
}
|
||||
|
||||
QCA::SecureArray plainTextResult = msg2.read();
|
||||
|
||||
qDebug() << enc.arrayToString( cipherText )
|
||||
<< " (in base 64) decrypts to: "
|
||||
<< plainTextResult.data();
|
||||
qDebug() << enc.arrayToString(cipherText) << " (in base 64) decrypts to: " << plainTextResult.data();
|
||||
|
||||
if (msg2.wasSigned()) {
|
||||
qDebug() << "Message was signed at "
|
||||
<< msg2.signer().timestamp();
|
||||
qDebug() << "Message was signed at " << msg2.signer().timestamp();
|
||||
} else {
|
||||
qDebug() << "Message was not signed";
|
||||
qDebug() << "Message was not signed";
|
||||
}
|
||||
|
||||
qDebug() << "Message used" << msg2.hashName() << "hashing algorithm";
|
||||
@ -155,7 +149,7 @@ int main(int argc, char** argv)
|
||||
QByteArray text("Got your message");
|
||||
|
||||
// Re-use the CMS and SecureMessageKeyList objects from the decrypt...
|
||||
QCA::SecureMessage signing( &anotherCms );
|
||||
QCA::SecureMessage signing(&anotherCms);
|
||||
signing.setSigners(privKeyList);
|
||||
|
||||
signing.startSign(QCA::SecureMessage::Detached);
|
||||
@ -166,23 +160,21 @@ int main(int argc, char** argv)
|
||||
signing.waitForFinished(1000);
|
||||
|
||||
// check to see if it worked
|
||||
if(!signing.success())
|
||||
{
|
||||
qWarning() << "Error signing: " << signing.errorCode();
|
||||
return 1;
|
||||
if (!signing.success()) {
|
||||
qWarning() << "Error signing: " << signing.errorCode();
|
||||
return 1;
|
||||
}
|
||||
|
||||
// get the result
|
||||
QByteArray signature = signing.signature();
|
||||
|
||||
qDebug() << "'" << text.data() << "', signature (converted to base 64), is: ";
|
||||
qDebug() << enc.arrayToString( signature );
|
||||
qDebug() << enc.arrayToString(signature);
|
||||
qDebug() << "Message uses" << signing.hashName() << "hashing algorithm";
|
||||
qDebug();
|
||||
|
||||
|
||||
// Now we go back to the first CMS, and re-use that.
|
||||
QCA::SecureMessage verifying( &cms );
|
||||
QCA::SecureMessage verifying(&cms);
|
||||
|
||||
// You have to pass the signature to startVerify(),
|
||||
// and the message to update()
|
||||
@ -193,23 +185,20 @@ int main(int argc, char** argv)
|
||||
verifying.waitForFinished(1000);
|
||||
|
||||
// check to see if it worked
|
||||
if(!verifying.success())
|
||||
{
|
||||
qWarning() << "Error verifying: " << verifying.errorCode();
|
||||
return 1;
|
||||
if (!verifying.success()) {
|
||||
qWarning() << "Error verifying: " << verifying.errorCode();
|
||||
return 1;
|
||||
}
|
||||
|
||||
QCA::SecureMessageSignature sign;
|
||||
sign = verifying.signer();
|
||||
// todo: dump some data out about the signer
|
||||
|
||||
if(verifying.verifySuccess())
|
||||
{
|
||||
qDebug() << "Message verified";
|
||||
if (verifying.verifySuccess()) {
|
||||
qDebug() << "Message verified";
|
||||
} else {
|
||||
qDebug() << "Message failed to verify:" << verifying.errorCode();
|
||||
qDebug() << "Message failed to verify:" << verifying.errorCode();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -28,11 +28,10 @@
|
||||
class QString;
|
||||
class QStringList;
|
||||
|
||||
namespace QCA
|
||||
{
|
||||
class PrivateKey;
|
||||
class CertificateChain;
|
||||
class KeyStoreEntry;
|
||||
namespace QCA {
|
||||
class PrivateKey;
|
||||
class CertificateChain;
|
||||
class KeyStoreEntry;
|
||||
}
|
||||
|
||||
class CertItemStore;
|
||||
@ -42,105 +41,105 @@ class CertItemPrivateLoaderPrivate;
|
||||
class CertItem
|
||||
{
|
||||
public:
|
||||
enum StorageType
|
||||
{
|
||||
File,
|
||||
KeyStore
|
||||
};
|
||||
enum StorageType
|
||||
{
|
||||
File,
|
||||
KeyStore
|
||||
};
|
||||
|
||||
CertItem();
|
||||
CertItem(const CertItem &from);
|
||||
~CertItem();
|
||||
CertItem & operator=(const CertItem &from);
|
||||
CertItem();
|
||||
CertItem(const CertItem &from);
|
||||
~CertItem();
|
||||
CertItem &operator=(const CertItem &from);
|
||||
|
||||
QString name() const;
|
||||
QCA::CertificateChain certificateChain() const;
|
||||
bool havePrivate() const;
|
||||
StorageType storageType() const; // private key storage type
|
||||
bool isUsable() const; // file/provider present
|
||||
QString name() const;
|
||||
QCA::CertificateChain certificateChain() const;
|
||||
bool havePrivate() const;
|
||||
StorageType storageType() const; // private key storage type
|
||||
bool isUsable() const; // file/provider present
|
||||
|
||||
private:
|
||||
class Private;
|
||||
QSharedDataPointer<Private> d;
|
||||
class Private;
|
||||
QSharedDataPointer<Private> d;
|
||||
|
||||
friend class CertItemStore;
|
||||
friend class CertItemStorePrivate;
|
||||
friend class CertItemPrivateLoader;
|
||||
friend class CertItemPrivateLoaderPrivate;
|
||||
friend class CertItemStore;
|
||||
friend class CertItemStorePrivate;
|
||||
friend class CertItemPrivateLoader;
|
||||
friend class CertItemPrivateLoaderPrivate;
|
||||
};
|
||||
|
||||
class CertItemStore : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum IconType
|
||||
{
|
||||
IconCert,
|
||||
IconCrl,
|
||||
IconKeyBundle,
|
||||
IconPgpPub,
|
||||
IconPgpSec
|
||||
};
|
||||
enum IconType
|
||||
{
|
||||
IconCert,
|
||||
IconCrl,
|
||||
IconKeyBundle,
|
||||
IconPgpPub,
|
||||
IconPgpSec
|
||||
};
|
||||
|
||||
CertItemStore(QObject *parent = 0);
|
||||
~CertItemStore();
|
||||
CertItemStore(QObject *parent = nullptr);
|
||||
~CertItemStore();
|
||||
|
||||
int idFromRow(int row) const;
|
||||
int rowFromId(int id) const;
|
||||
CertItem itemFromId(int id) const;
|
||||
CertItem itemFromRow(int row) const;
|
||||
int idFromRow(int row) const;
|
||||
int rowFromId(int id) const;
|
||||
CertItem itemFromId(int id) const;
|
||||
CertItem itemFromRow(int row) const;
|
||||
|
||||
QList<CertItem> items() const;
|
||||
QList<CertItem> items() const;
|
||||
|
||||
QStringList save() const;
|
||||
bool load(const QStringList &in);
|
||||
QStringList save() const;
|
||||
bool load(const QStringList &in);
|
||||
|
||||
// returns a reqId
|
||||
int addFromFile(const QString &fileName);
|
||||
int addFromKeyStore(const QCA::KeyStoreEntry &entry);
|
||||
int addUser(const QCA::CertificateChain &chain);
|
||||
// returns a reqId
|
||||
int addFromFile(const QString &fileName);
|
||||
int addFromKeyStore(const QCA::KeyStoreEntry &entry);
|
||||
int addUser(const QCA::CertificateChain &chain);
|
||||
|
||||
void updateChain(int id, const QCA::CertificateChain &chain);
|
||||
void updateChain(int id, const QCA::CertificateChain &chain);
|
||||
|
||||
void removeItem(int id);
|
||||
void removeItem(int id);
|
||||
|
||||
void setIcon(IconType type, const QPixmap &icon);
|
||||
void setIcon(IconType type, const QPixmap &icon);
|
||||
|
||||
// reimplemented
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const;
|
||||
QVariant data(const QModelIndex &index, int role) const;
|
||||
Qt::ItemFlags flags(const QModelIndex &index) const;
|
||||
bool setData(const QModelIndex &index, const QVariant &value, int role);
|
||||
// reimplemented
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const;
|
||||
QVariant data(const QModelIndex &index, int role) const;
|
||||
Qt::ItemFlags flags(const QModelIndex &index) const;
|
||||
bool setData(const QModelIndex &index, const QVariant &value, int role);
|
||||
|
||||
signals:
|
||||
void addSuccess(int reqId, int id);
|
||||
void addFailed(int reqId);
|
||||
Q_SIGNALS:
|
||||
void addSuccess(int reqId, int id);
|
||||
void addFailed(int reqId);
|
||||
|
||||
private:
|
||||
friend class CertItemStorePrivate;
|
||||
CertItemStorePrivate *d;
|
||||
friend class CertItemStorePrivate;
|
||||
CertItemStorePrivate *d;
|
||||
|
||||
friend class CertItemPrivateLoader;
|
||||
friend class CertItemPrivateLoaderPrivate;
|
||||
friend class CertItemPrivateLoader;
|
||||
friend class CertItemPrivateLoaderPrivate;
|
||||
};
|
||||
|
||||
class CertItemPrivateLoader : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit CertItemPrivateLoader(CertItemStore *store, QObject *parent = 0);
|
||||
~CertItemPrivateLoader();
|
||||
explicit CertItemPrivateLoader(CertItemStore *store, QObject *parent = nullptr);
|
||||
~CertItemPrivateLoader();
|
||||
|
||||
void start(int id);
|
||||
void start(int id);
|
||||
|
||||
QCA::PrivateKey privateKey() const;
|
||||
QCA::PrivateKey privateKey() const;
|
||||
|
||||
signals:
|
||||
void finished();
|
||||
Q_SIGNALS:
|
||||
void finished();
|
||||
|
||||
private:
|
||||
friend class CertItemPrivateLoaderPrivate;
|
||||
CertItemPrivateLoaderPrivate *d;
|
||||
friend class CertItemPrivateLoaderPrivate;
|
||||
CertItemPrivateLoaderPrivate *d;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -21,146 +21,165 @@
|
||||
|
||||
#include "certviewdlg.h"
|
||||
|
||||
#include <QtCore>
|
||||
#include <QtGui>
|
||||
#include <QtCrypto>
|
||||
#include "ui_certview.h"
|
||||
#include <QtCore>
|
||||
#include <QtCrypto>
|
||||
#include <QtGui>
|
||||
|
||||
// from qcatool
|
||||
class InfoType
|
||||
{
|
||||
public:
|
||||
QCA::CertificateInfoType type;
|
||||
QString varname;
|
||||
QString shortname;
|
||||
QString name;
|
||||
QString desc;
|
||||
QCA::CertificateInfoType type;
|
||||
QString varname;
|
||||
QString shortname;
|
||||
QString name;
|
||||
QString desc;
|
||||
|
||||
InfoType()
|
||||
{
|
||||
}
|
||||
InfoType()
|
||||
{
|
||||
}
|
||||
|
||||
InfoType(QCA::CertificateInfoType _type, const QString &_varname, const QString &_shortname, const QString &_name, const QString &_desc) :
|
||||
type(_type),
|
||||
varname(_varname),
|
||||
shortname(_shortname),
|
||||
name(_name),
|
||||
desc(_desc)
|
||||
{
|
||||
}
|
||||
InfoType(QCA::CertificateInfoType _type,
|
||||
const QString & _varname,
|
||||
const QString & _shortname,
|
||||
const QString & _name,
|
||||
const QString & _desc)
|
||||
: type(_type)
|
||||
, varname(_varname)
|
||||
, shortname(_shortname)
|
||||
, name(_name)
|
||||
, desc(_desc)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
static QList<InfoType> makeInfoTypeList(bool legacyEmail = false)
|
||||
{
|
||||
QList<InfoType> out;
|
||||
out += InfoType(QCA::CommonName, "CommonName", "CN", CertViewDlg::tr("Common Name (CN)"), "Full name, domain, anything");
|
||||
out += InfoType(QCA::Email, "Email", "", CertViewDlg::tr("Email Address"), "");
|
||||
if(legacyEmail)
|
||||
out += InfoType(QCA::EmailLegacy, "EmailLegacy", "", CertViewDlg::tr("PKCS#9 Email Address"), "");
|
||||
out += InfoType(QCA::Organization, "Organization", "O", CertViewDlg::tr("Organization (O)"), "Company, group, etc");
|
||||
out += InfoType(QCA::OrganizationalUnit, "OrganizationalUnit", "OU", CertViewDlg::tr("Organizational Unit (OU)"), "Division/branch of organization");
|
||||
out += InfoType(QCA::Locality, "Locality", "", CertViewDlg::tr("Locality (L)"), "City, shire, part of a state");
|
||||
out += InfoType(QCA::State, "State", "", CertViewDlg::tr("State (ST)"), "State within the country");
|
||||
out += InfoType(QCA::Country, "Country", "C", CertViewDlg::tr("Country Code (C)"), "2-letter code");
|
||||
out += InfoType(QCA::IncorporationLocality, "IncorporationLocality", "", CertViewDlg::tr("Incorporation Locality"), "For EV certificates");
|
||||
out += InfoType(QCA::IncorporationState, "IncorporationState", "", CertViewDlg::tr("Incorporation State"), "For EV certificates");
|
||||
out += InfoType(QCA::IncorporationCountry, "IncorporationCountry", "", CertViewDlg::tr("Incorporation Country"), "For EV certificates");
|
||||
out += InfoType(QCA::URI, "URI", "", CertViewDlg::tr("URI"), "");
|
||||
out += InfoType(QCA::DNS, "DNS", "", CertViewDlg::tr("Domain Name"), "Domain (dnsName)");
|
||||
out += InfoType(QCA::IPAddress, "IPAddress", "", CertViewDlg::tr("IP Adddress"), "");
|
||||
out += InfoType(QCA::XMPP, "XMPP", "", CertViewDlg::tr("XMPP Address (JID)"), "From RFC 3920 (id-on-xmppAddr)");
|
||||
return out;
|
||||
QList<InfoType> out;
|
||||
out += InfoType(
|
||||
QCA::CommonName, "CommonName", "CN", CertViewDlg::tr("Common Name (CN)"), "Full name, domain, anything");
|
||||
out += InfoType(QCA::Email, "Email", "", CertViewDlg::tr("Email Address"), "");
|
||||
if (legacyEmail)
|
||||
out += InfoType(QCA::EmailLegacy, "EmailLegacy", "", CertViewDlg::tr("PKCS#9 Email Address"), "");
|
||||
out += InfoType(QCA::Organization, "Organization", "O", CertViewDlg::tr("Organization (O)"), "Company, group, etc");
|
||||
out += InfoType(QCA::OrganizationalUnit,
|
||||
"OrganizationalUnit",
|
||||
"OU",
|
||||
CertViewDlg::tr("Organizational Unit (OU)"),
|
||||
"Division/branch of organization");
|
||||
out += InfoType(QCA::Locality, "Locality", "", CertViewDlg::tr("Locality (L)"), "City, shire, part of a state");
|
||||
out += InfoType(QCA::State, "State", "", CertViewDlg::tr("State (ST)"), "State within the country");
|
||||
out += InfoType(QCA::Country, "Country", "C", CertViewDlg::tr("Country Code (C)"), "2-letter code");
|
||||
out += InfoType(QCA::IncorporationLocality,
|
||||
"IncorporationLocality",
|
||||
"",
|
||||
CertViewDlg::tr("Incorporation Locality"),
|
||||
"For EV certificates");
|
||||
out += InfoType(QCA::IncorporationState,
|
||||
"IncorporationState",
|
||||
"",
|
||||
CertViewDlg::tr("Incorporation State"),
|
||||
"For EV certificates");
|
||||
out += InfoType(QCA::IncorporationCountry,
|
||||
"IncorporationCountry",
|
||||
"",
|
||||
CertViewDlg::tr("Incorporation Country"),
|
||||
"For EV certificates");
|
||||
out += InfoType(QCA::URI, "URI", "", CertViewDlg::tr("URI"), "");
|
||||
out += InfoType(QCA::DNS, "DNS", "", CertViewDlg::tr("Domain Name"), "Domain (dnsName)");
|
||||
out += InfoType(QCA::IPAddress, "IPAddress", "", CertViewDlg::tr("IP Adddress"), "");
|
||||
out += InfoType(QCA::XMPP, "XMPP", "", CertViewDlg::tr("XMPP Address (JID)"), "From RFC 3920 (id-on-xmppAddr)");
|
||||
return out;
|
||||
}
|
||||
|
||||
static QString try_print_info(const QString &name, const QStringList &values)
|
||||
{
|
||||
QString out;
|
||||
if(!values.isEmpty())
|
||||
{
|
||||
QString value = values.join(", ");
|
||||
out = QString(" ") + CertViewDlg::tr("%1: %2").arg(name, value) + '\n';
|
||||
}
|
||||
return out;
|
||||
QString out;
|
||||
if (!values.isEmpty()) {
|
||||
QString value = values.join(", ");
|
||||
out = QString(" ") + CertViewDlg::tr("%1: %2").arg(name, value) + '\n';
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
static QString print_info(const QString &title, const QCA::CertificateInfo &info)
|
||||
{
|
||||
QString out;
|
||||
QList<InfoType> list = makeInfoTypeList();
|
||||
out += title + '\n';
|
||||
foreach(const InfoType &t, list)
|
||||
out += try_print_info(t.name, info.values(t.type));
|
||||
return out;
|
||||
QString out;
|
||||
QList<InfoType> list = makeInfoTypeList();
|
||||
out += title + '\n';
|
||||
foreach (const InfoType &t, list)
|
||||
out += try_print_info(t.name, info.values(t.type));
|
||||
return out;
|
||||
}
|
||||
|
||||
static QString cert_info_string(const QCA::Certificate &cert)
|
||||
{
|
||||
QString out;
|
||||
out += CertViewDlg::tr("Serial Number: %1").arg(cert.serialNumber().toString()) + '\n';
|
||||
out += print_info(CertViewDlg::tr("Subject"), cert.subjectInfo());
|
||||
out += print_info(CertViewDlg::tr("Issuer"), cert.issuerInfo());
|
||||
out += CertViewDlg::tr("Validity") + '\n';
|
||||
out += QString(" ") + CertViewDlg::tr("Not before: %1").arg(cert.notValidBefore().toString()) + '\n';
|
||||
out += QString(" ") + CertViewDlg::tr("Not after: %1").arg(cert.notValidAfter().toString()) + '\n';
|
||||
return out;
|
||||
QString out;
|
||||
out += CertViewDlg::tr("Serial Number: %1").arg(cert.serialNumber().toString()) + '\n';
|
||||
out += print_info(CertViewDlg::tr("Subject"), cert.subjectInfo());
|
||||
out += print_info(CertViewDlg::tr("Issuer"), cert.issuerInfo());
|
||||
out += CertViewDlg::tr("Validity") + '\n';
|
||||
out += QString(" ") + CertViewDlg::tr("Not before: %1").arg(cert.notValidBefore().toString()) + '\n';
|
||||
out += QString(" ") + CertViewDlg::tr("Not after: %1").arg(cert.notValidAfter().toString()) + '\n';
|
||||
return out;
|
||||
}
|
||||
|
||||
class CertViewDlg::Private : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
public:
|
||||
CertViewDlg *q;
|
||||
Ui_CertView ui;
|
||||
QCA::CertificateChain chain;
|
||||
CertViewDlg * q;
|
||||
Ui_CertView ui;
|
||||
QCA::CertificateChain chain;
|
||||
|
||||
Private(CertViewDlg *_q) :
|
||||
QObject(_q),
|
||||
q(_q)
|
||||
{
|
||||
ui.setupUi(q);
|
||||
connect(ui.cb_chain, SIGNAL(activated(int)), SLOT(cb_activated(int)));
|
||||
ui.lb_info->setTextInteractionFlags(Qt::TextSelectableByMouse);
|
||||
}
|
||||
Private(CertViewDlg *_q)
|
||||
: QObject(_q)
|
||||
, q(_q)
|
||||
{
|
||||
ui.setupUi(q);
|
||||
connect(ui.cb_chain, SIGNAL(activated(int)), SLOT(cb_activated(int)));
|
||||
ui.lb_info->setTextInteractionFlags(Qt::TextSelectableByMouse);
|
||||
}
|
||||
|
||||
void update()
|
||||
{
|
||||
QStringList names = QCA::makeFriendlyNames(chain);
|
||||
ui.cb_chain->clear();
|
||||
foreach(const QString &s, names)
|
||||
ui.cb_chain->insertItem(ui.cb_chain->count(), s);
|
||||
updateInfo();
|
||||
}
|
||||
void update()
|
||||
{
|
||||
QStringList names = QCA::makeFriendlyNames(chain);
|
||||
ui.cb_chain->clear();
|
||||
foreach (const QString &s, names)
|
||||
ui.cb_chain->insertItem(ui.cb_chain->count(), s);
|
||||
updateInfo();
|
||||
}
|
||||
|
||||
void updateInfo()
|
||||
{
|
||||
int x = ui.cb_chain->currentIndex();
|
||||
if(x == -1)
|
||||
{
|
||||
ui.lb_info->setText("");
|
||||
return;
|
||||
}
|
||||
void updateInfo()
|
||||
{
|
||||
int x = ui.cb_chain->currentIndex();
|
||||
if (x == -1) {
|
||||
ui.lb_info->setText("");
|
||||
return;
|
||||
}
|
||||
|
||||
ui.lb_info->setText(cert_info_string(chain[x]));
|
||||
}
|
||||
ui.lb_info->setText(cert_info_string(chain[x]));
|
||||
}
|
||||
|
||||
private slots:
|
||||
void cb_activated(int)
|
||||
{
|
||||
updateInfo();
|
||||
}
|
||||
private Q_SLOTS:
|
||||
void cb_activated(int)
|
||||
{
|
||||
updateInfo();
|
||||
}
|
||||
};
|
||||
|
||||
CertViewDlg::CertViewDlg(const QCA::CertificateChain &chain, QWidget *parent) :
|
||||
QDialog(parent)
|
||||
CertViewDlg::CertViewDlg(const QCA::CertificateChain &chain, QWidget *parent)
|
||||
: QDialog(parent)
|
||||
{
|
||||
d = new Private(this);
|
||||
d->chain = chain;
|
||||
d->update();
|
||||
d = new Private(this);
|
||||
d->chain = chain;
|
||||
d->update();
|
||||
}
|
||||
|
||||
CertViewDlg::~CertViewDlg()
|
||||
{
|
||||
delete d;
|
||||
delete d;
|
||||
}
|
||||
|
||||
#include "certviewdlg.moc"
|
||||
|
@ -24,21 +24,20 @@
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
namespace QCA
|
||||
{
|
||||
class CertificateChain;
|
||||
namespace QCA {
|
||||
class CertificateChain;
|
||||
}
|
||||
|
||||
class CertViewDlg : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit CertViewDlg(const QCA::CertificateChain &chain, QWidget *parent = 0);
|
||||
~CertViewDlg();
|
||||
explicit CertViewDlg(const QCA::CertificateChain &chain, QWidget *parent = 0);
|
||||
~CertViewDlg();
|
||||
|
||||
private:
|
||||
class Private;
|
||||
Private *d;
|
||||
class Private;
|
||||
Private *d;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -21,405 +21,394 @@
|
||||
|
||||
#include "keyselectdlg.h"
|
||||
|
||||
#include <QtCore>
|
||||
#include <QtGui>
|
||||
#include <QtCrypto>
|
||||
#include <QPushButton>
|
||||
#include "ui_keyselect.h"
|
||||
#include <QMenu>
|
||||
#include <QMessageBox>
|
||||
#include "ui_keyselect.h"
|
||||
#include <QPushButton>
|
||||
#include <QtCore>
|
||||
#include <QtCrypto>
|
||||
#include <QtGui>
|
||||
|
||||
#define ONLY_SHOW_KEYBUNDLE
|
||||
|
||||
typedef QMap<KeySelectDlg::IconType,QPixmap> KeyStoreIconset;
|
||||
typedef QMap<KeySelectDlg::IconType, QPixmap> KeyStoreIconset;
|
||||
|
||||
class KeyStoreItemShared
|
||||
{
|
||||
public:
|
||||
KeyStoreIconset iconset;
|
||||
QString notAvailableString;
|
||||
KeyStoreIconset iconset;
|
||||
QString notAvailableString;
|
||||
};
|
||||
|
||||
class KeyStoreItem : public QStandardItem
|
||||
{
|
||||
public:
|
||||
enum Type
|
||||
{
|
||||
Store = UserType,
|
||||
Entry
|
||||
};
|
||||
enum Type
|
||||
{
|
||||
Store = UserType,
|
||||
Entry
|
||||
};
|
||||
|
||||
enum Role
|
||||
{
|
||||
NameRole = Qt::UserRole,
|
||||
SubTypeRole,
|
||||
AvailabilityRole,
|
||||
PositionRole
|
||||
};
|
||||
enum Role
|
||||
{
|
||||
NameRole = Qt::UserRole,
|
||||
SubTypeRole,
|
||||
AvailabilityRole,
|
||||
PositionRole
|
||||
};
|
||||
|
||||
QPixmap entryTypeToIcon(QCA::KeyStoreEntry::Type type) const
|
||||
{
|
||||
QPixmap out;
|
||||
if(!_shared)
|
||||
return out;
|
||||
const KeyStoreIconset &iconset = _shared->iconset;
|
||||
switch(type)
|
||||
{
|
||||
case QCA::KeyStoreEntry::TypeKeyBundle: out = iconset[KeySelectDlg::IconKeyBundle]; break;
|
||||
case QCA::KeyStoreEntry::TypeCertificate: out = iconset[KeySelectDlg::IconCert]; break;
|
||||
case QCA::KeyStoreEntry::TypeCRL: out = iconset[KeySelectDlg::IconCrl]; break;
|
||||
case QCA::KeyStoreEntry::TypePGPSecretKey: out = iconset[KeySelectDlg::IconPgpSec]; break;
|
||||
case QCA::KeyStoreEntry::TypePGPPublicKey: out = iconset[KeySelectDlg::IconPgpPub]; break;
|
||||
default: break;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
QPixmap entryTypeToIcon(QCA::KeyStoreEntry::Type type) const
|
||||
{
|
||||
QPixmap out;
|
||||
if (!_shared)
|
||||
return out;
|
||||
const KeyStoreIconset &iconset = _shared->iconset;
|
||||
switch (type) {
|
||||
case QCA::KeyStoreEntry::TypeKeyBundle:
|
||||
out = iconset[KeySelectDlg::IconKeyBundle];
|
||||
break;
|
||||
case QCA::KeyStoreEntry::TypeCertificate:
|
||||
out = iconset[KeySelectDlg::IconCert];
|
||||
break;
|
||||
case QCA::KeyStoreEntry::TypeCRL:
|
||||
out = iconset[KeySelectDlg::IconCrl];
|
||||
break;
|
||||
case QCA::KeyStoreEntry::TypePGPSecretKey:
|
||||
out = iconset[KeySelectDlg::IconPgpSec];
|
||||
break;
|
||||
case QCA::KeyStoreEntry::TypePGPPublicKey:
|
||||
out = iconset[KeySelectDlg::IconPgpPub];
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
Type _type;
|
||||
KeyStoreItemShared *_shared;
|
||||
Type _type;
|
||||
KeyStoreItemShared *_shared;
|
||||
|
||||
QCA::KeyStore *keyStore;
|
||||
QCA::KeyStoreEntry keyStoreEntry;
|
||||
QCA::KeyStore * keyStore;
|
||||
QCA::KeyStoreEntry keyStoreEntry;
|
||||
|
||||
KeyStoreItem(Type type, KeyStoreItemShared *shared) :
|
||||
_type(type),
|
||||
_shared(shared)
|
||||
{
|
||||
setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
|
||||
}
|
||||
KeyStoreItem(Type type, KeyStoreItemShared *shared)
|
||||
: _type(type)
|
||||
, _shared(shared)
|
||||
{
|
||||
setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
|
||||
}
|
||||
|
||||
void setStore(const QString &name, QCA::KeyStore::Type type)
|
||||
{
|
||||
setData(name, NameRole);
|
||||
setData((int)type, SubTypeRole);
|
||||
}
|
||||
void setStore(const QString &name, QCA::KeyStore::Type type)
|
||||
{
|
||||
setData(name, NameRole);
|
||||
setData((int)type, SubTypeRole);
|
||||
}
|
||||
|
||||
void setEntry(const QString &name, QCA::KeyStoreEntry::Type type, bool available, int pos)
|
||||
{
|
||||
setData(name, NameRole);
|
||||
setData((int)type, SubTypeRole);
|
||||
setData(available, AvailabilityRole);
|
||||
setData(pos, PositionRole);
|
||||
}
|
||||
void setEntry(const QString &name, QCA::KeyStoreEntry::Type type, bool available, int pos)
|
||||
{
|
||||
setData(name, NameRole);
|
||||
setData((int)type, SubTypeRole);
|
||||
setData(available, AvailabilityRole);
|
||||
setData(pos, PositionRole);
|
||||
}
|
||||
|
||||
virtual QVariant data(int role) const
|
||||
{
|
||||
if(role == Qt::DisplayRole)
|
||||
{
|
||||
if(_type == Store)
|
||||
{
|
||||
return data(NameRole).toString();
|
||||
}
|
||||
else if(_type == Entry)
|
||||
{
|
||||
QString str = data(NameRole).toString();
|
||||
if(_shared && !data(AvailabilityRole).toBool())
|
||||
str += QString(" ") + _shared->notAvailableString;
|
||||
return str;
|
||||
}
|
||||
else
|
||||
return QStandardItem::data(role);
|
||||
}
|
||||
else if(role == Qt::DecorationRole)
|
||||
{
|
||||
if(_type == Entry)
|
||||
{
|
||||
QCA::KeyStoreEntry::Type type = (QCA::KeyStoreEntry::Type)data(SubTypeRole).toInt();
|
||||
return entryTypeToIcon(type);
|
||||
}
|
||||
else
|
||||
return QStandardItem::data(role);
|
||||
}
|
||||
else
|
||||
return QStandardItem::data(role);
|
||||
}
|
||||
virtual QVariant data(int role) const
|
||||
{
|
||||
if (role == Qt::DisplayRole) {
|
||||
if (_type == Store) {
|
||||
return data(NameRole).toString();
|
||||
} else if (_type == Entry) {
|
||||
QString str = data(NameRole).toString();
|
||||
if (_shared && !data(AvailabilityRole).toBool())
|
||||
str += QString(" ") + _shared->notAvailableString;
|
||||
return str;
|
||||
} else
|
||||
return QStandardItem::data(role);
|
||||
} else if (role == Qt::DecorationRole) {
|
||||
if (_type == Entry) {
|
||||
QCA::KeyStoreEntry::Type type = (QCA::KeyStoreEntry::Type)data(SubTypeRole).toInt();
|
||||
return entryTypeToIcon(type);
|
||||
} else
|
||||
return QStandardItem::data(role);
|
||||
} else
|
||||
return QStandardItem::data(role);
|
||||
}
|
||||
|
||||
virtual int type() const
|
||||
{
|
||||
return _type;
|
||||
}
|
||||
virtual int type() const
|
||||
{
|
||||
return _type;
|
||||
}
|
||||
|
||||
virtual QStandardItem *clone() const
|
||||
{
|
||||
return new KeyStoreItem(*this);
|
||||
}
|
||||
virtual QStandardItem *clone() const
|
||||
{
|
||||
return new KeyStoreItem(*this);
|
||||
}
|
||||
};
|
||||
|
||||
class KeyStoreModel : public QStandardItemModel
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
public:
|
||||
KeyStoreItemShared shared;
|
||||
KeyStoreItemShared shared;
|
||||
|
||||
QCA::KeyStoreManager ksm;
|
||||
QCA::KeyStoreManager ksm;
|
||||
|
||||
KeyStoreModel(QObject *parent = 0) :
|
||||
QStandardItemModel(parent), ksm(this)
|
||||
{
|
||||
shared.notAvailableString = tr("(not available)");
|
||||
KeyStoreModel(QObject *parent = 0)
|
||||
: QStandardItemModel(parent)
|
||||
, ksm(this)
|
||||
{
|
||||
shared.notAvailableString = tr("(not available)");
|
||||
|
||||
// make sure keystores are started
|
||||
QCA::KeyStoreManager::start();
|
||||
// make sure keystores are started
|
||||
QCA::KeyStoreManager::start();
|
||||
|
||||
connect(&ksm, SIGNAL(keyStoreAvailable(const QString &)), SLOT(ks_available(const QString &)));
|
||||
QStringList list = ksm.keyStores();
|
||||
foreach(const QString &s, list)
|
||||
ks_available(s);
|
||||
connect(&ksm, SIGNAL(keyStoreAvailable(const QString &)), SLOT(ks_available(const QString &)));
|
||||
QStringList list = ksm.keyStores();
|
||||
foreach (const QString &s, list)
|
||||
ks_available(s);
|
||||
|
||||
setSortRole(KeyStoreItem::PositionRole);
|
||||
}
|
||||
setSortRole(KeyStoreItem::PositionRole);
|
||||
}
|
||||
|
||||
KeyStoreItem *itemFromStore(QCA::KeyStore *ks) const
|
||||
{
|
||||
for(int n = 0; n < rowCount(); ++n)
|
||||
{
|
||||
KeyStoreItem *i = (KeyStoreItem *)item(n);
|
||||
if(i->keyStore == ks)
|
||||
return i;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
KeyStoreItem *itemFromStore(QCA::KeyStore *ks) const
|
||||
{
|
||||
for (int n = 0; n < rowCount(); ++n) {
|
||||
KeyStoreItem *i = (KeyStoreItem *)item(n);
|
||||
if (i->keyStore == ks)
|
||||
return i;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private slots:
|
||||
void ks_available(const QString &keyStoreId)
|
||||
{
|
||||
QCA::KeyStore *ks = new QCA::KeyStore(keyStoreId, &ksm);
|
||||
private Q_SLOTS:
|
||||
void ks_available(const QString &keyStoreId)
|
||||
{
|
||||
QCA::KeyStore *ks = new QCA::KeyStore(keyStoreId, &ksm);
|
||||
|
||||
#ifdef ONLY_SHOW_KEYBUNDLE
|
||||
// only list stores containing keybundles (non-pgp identities)
|
||||
if(!ks->holdsIdentities() || ks->type() == QCA::KeyStore::PGPKeyring)
|
||||
return;
|
||||
// only list stores containing keybundles (non-pgp identities)
|
||||
if (!ks->holdsIdentities() || ks->type() == QCA::KeyStore::PGPKeyring)
|
||||
return;
|
||||
#endif
|
||||
|
||||
connect(ks, SIGNAL(updated()), SLOT(ks_updated()));
|
||||
connect(ks, SIGNAL(unavailable()), SLOT(ks_unavailable()));
|
||||
connect(ks, SIGNAL(updated()), SLOT(ks_updated()));
|
||||
connect(ks, SIGNAL(unavailable()), SLOT(ks_unavailable()));
|
||||
|
||||
KeyStoreItem *store_item = new KeyStoreItem(KeyStoreItem::Store, &shared);
|
||||
store_item->setStore(ks->name(), ks->type());
|
||||
store_item->keyStore = ks;
|
||||
ks->startAsynchronousMode();
|
||||
appendRow(store_item);
|
||||
}
|
||||
KeyStoreItem *store_item = new KeyStoreItem(KeyStoreItem::Store, &shared);
|
||||
store_item->setStore(ks->name(), ks->type());
|
||||
store_item->keyStore = ks;
|
||||
ks->startAsynchronousMode();
|
||||
appendRow(store_item);
|
||||
}
|
||||
|
||||
void ks_updated()
|
||||
{
|
||||
QCA::KeyStore *ks = (QCA::KeyStore *)sender();
|
||||
KeyStoreItem *store_item = itemFromStore(ks);
|
||||
Q_ASSERT(store_item);
|
||||
void ks_updated()
|
||||
{
|
||||
QCA::KeyStore *ks = (QCA::KeyStore *)sender();
|
||||
KeyStoreItem * store_item = itemFromStore(ks);
|
||||
Q_ASSERT(store_item);
|
||||
|
||||
QList<QCA::KeyStoreEntry> newEntries = ks->entryList();
|
||||
QList<QCA::KeyStoreEntry> newEntries = ks->entryList();
|
||||
|
||||
#ifdef ONLY_SHOW_KEYBUNDLE
|
||||
// ignore entries that are not keybundles
|
||||
for(int n = 0; n < newEntries.count(); ++n)
|
||||
{
|
||||
if(newEntries[n].type() != QCA::KeyStoreEntry::TypeKeyBundle)
|
||||
{
|
||||
newEntries.removeAt(n);
|
||||
--n; // adjust position
|
||||
}
|
||||
}
|
||||
// ignore entries that are not keybundles
|
||||
for (int n = 0; n < newEntries.count(); ++n) {
|
||||
if (newEntries[n].type() != QCA::KeyStoreEntry::TypeKeyBundle) {
|
||||
newEntries.removeAt(n);
|
||||
--n; // adjust position
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// update the store item itself
|
||||
store_item->setStore(ks->name(), ks->type());
|
||||
// update the store item itself
|
||||
store_item->setStore(ks->name(), ks->type());
|
||||
|
||||
// handle removed child entries
|
||||
for(int n = 0; n < store_item->rowCount(); ++n)
|
||||
{
|
||||
KeyStoreItem *i = (KeyStoreItem *)store_item->child(n);
|
||||
// handle removed child entries
|
||||
for (int n = 0; n < store_item->rowCount(); ++n) {
|
||||
KeyStoreItem *i = (KeyStoreItem *)store_item->child(n);
|
||||
|
||||
// is the existing entry in the new list?
|
||||
bool found = false;
|
||||
foreach(const QCA::KeyStoreEntry &ne, newEntries)
|
||||
{
|
||||
if(ne.id() == i->keyStoreEntry.id())
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// is the existing entry in the new list?
|
||||
bool found = false;
|
||||
foreach (const QCA::KeyStoreEntry &ne, newEntries) {
|
||||
if (ne.id() == i->keyStoreEntry.id()) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// if not, remove it
|
||||
if(!found)
|
||||
{
|
||||
store_item->removeRow(n);
|
||||
--n; // adjust position
|
||||
}
|
||||
}
|
||||
// if not, remove it
|
||||
if (!found) {
|
||||
store_item->removeRow(n);
|
||||
--n; // adjust position
|
||||
}
|
||||
}
|
||||
|
||||
// handle added/updated child entries
|
||||
for(int n = 0; n < newEntries.count(); ++n)
|
||||
{
|
||||
const QCA::KeyStoreEntry &ne = newEntries[n];
|
||||
// handle added/updated child entries
|
||||
for (int n = 0; n < newEntries.count(); ++n) {
|
||||
const QCA::KeyStoreEntry &ne = newEntries[n];
|
||||
|
||||
// was this entry in the original list?
|
||||
KeyStoreItem *entry_item = 0;
|
||||
for(int k = 0; k < store_item->rowCount(); ++k)
|
||||
{
|
||||
KeyStoreItem *i = (KeyStoreItem *)store_item->child(k);
|
||||
if(i->keyStoreEntry.id() == ne.id())
|
||||
{
|
||||
entry_item = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// was this entry in the original list?
|
||||
KeyStoreItem *entry_item = 0;
|
||||
for (int k = 0; k < store_item->rowCount(); ++k) {
|
||||
KeyStoreItem *i = (KeyStoreItem *)store_item->child(k);
|
||||
if (i->keyStoreEntry.id() == ne.id()) {
|
||||
entry_item = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// if not, add it
|
||||
if(!entry_item)
|
||||
{
|
||||
entry_item = new KeyStoreItem(KeyStoreItem::Entry, &shared);
|
||||
entry_item->keyStoreEntry = ne;
|
||||
entry_item->setEntry(newEntries[n].name(), newEntries[n].type(), newEntries[n].isAvailable(), n);
|
||||
store_item->appendRow(entry_item);
|
||||
}
|
||||
// if so, update it
|
||||
else
|
||||
{
|
||||
entry_item->keyStoreEntry = ne;
|
||||
entry_item->setEntry(newEntries[n].name(), newEntries[n].type(), newEntries[n].isAvailable(), n);
|
||||
}
|
||||
}
|
||||
// if not, add it
|
||||
if (!entry_item) {
|
||||
entry_item = new KeyStoreItem(KeyStoreItem::Entry, &shared);
|
||||
entry_item->keyStoreEntry = ne;
|
||||
entry_item->setEntry(newEntries[n].name(), newEntries[n].type(), newEntries[n].isAvailable(), n);
|
||||
store_item->appendRow(entry_item);
|
||||
}
|
||||
// if so, update it
|
||||
else {
|
||||
entry_item->keyStoreEntry = ne;
|
||||
entry_item->setEntry(newEntries[n].name(), newEntries[n].type(), newEntries[n].isAvailable(), n);
|
||||
}
|
||||
}
|
||||
|
||||
store_item->sortChildren(0);
|
||||
}
|
||||
store_item->sortChildren(0);
|
||||
}
|
||||
|
||||
void ks_unavailable()
|
||||
{
|
||||
QCA::KeyStore *ks = (QCA::KeyStore *)sender();
|
||||
KeyStoreItem *store_item = itemFromStore(ks);
|
||||
Q_ASSERT(store_item);
|
||||
void ks_unavailable()
|
||||
{
|
||||
QCA::KeyStore *ks = (QCA::KeyStore *)sender();
|
||||
KeyStoreItem * store_item = itemFromStore(ks);
|
||||
Q_ASSERT(store_item);
|
||||
|
||||
store_item->removeRows(0, store_item->rowCount());
|
||||
removeRow(store_item->row());
|
||||
delete ks;
|
||||
}
|
||||
store_item->removeRows(0, store_item->rowCount());
|
||||
removeRow(store_item->row());
|
||||
delete ks;
|
||||
}
|
||||
};
|
||||
|
||||
class KeySelectDlg::Private : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
public:
|
||||
KeySelectDlg *q;
|
||||
Ui_KeySelect ui;
|
||||
KeyStoreModel *model;
|
||||
QCA::KeyStoreEntry cur_entry;
|
||||
QAction *actionView;
|
||||
KeySelectDlg * q;
|
||||
Ui_KeySelect ui;
|
||||
KeyStoreModel * model;
|
||||
QCA::KeyStoreEntry cur_entry;
|
||||
QAction * actionView;
|
||||
|
||||
Private(KeySelectDlg *_q) :
|
||||
QObject(_q),
|
||||
q(_q)
|
||||
{
|
||||
ui.setupUi(q);
|
||||
Private(KeySelectDlg *_q)
|
||||
: QObject(_q)
|
||||
, q(_q)
|
||||
{
|
||||
ui.setupUi(q);
|
||||
|
||||
model = new KeyStoreModel(this);
|
||||
connect(&model->ksm, SIGNAL(busyStarted()), SLOT(ksm_busyStarted()));
|
||||
connect(&model->ksm, SIGNAL(busyFinished()), SLOT(ksm_busyFinished()));
|
||||
if(model->ksm.isBusy())
|
||||
ksm_busyStarted();
|
||||
model = new KeyStoreModel(this);
|
||||
connect(&model->ksm, SIGNAL(busyStarted()), SLOT(ksm_busyStarted()));
|
||||
connect(&model->ksm, SIGNAL(busyFinished()), SLOT(ksm_busyFinished()));
|
||||
if (model->ksm.isBusy())
|
||||
ksm_busyStarted();
|
||||
|
||||
ui.lv_stores->header()->hide();
|
||||
ui.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
|
||||
ui.lv_stores->setModel(model);
|
||||
ui.lv_stores->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
connect(ui.lv_stores->selectionModel(), SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)), SLOT(stores_selectionChanged(const QItemSelection &, const QItemSelection &)));
|
||||
connect(ui.lv_stores, SIGNAL(customContextMenuRequested(const QPoint &)), SLOT(stores_customContextMenuRequested(const QPoint &)));
|
||||
ui.lv_stores->header()->hide();
|
||||
ui.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
|
||||
ui.lv_stores->setModel(model);
|
||||
ui.lv_stores->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
connect(ui.lv_stores->selectionModel(),
|
||||
SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)),
|
||||
SLOT(stores_selectionChanged(const QItemSelection &, const QItemSelection &)));
|
||||
connect(ui.lv_stores,
|
||||
SIGNAL(customContextMenuRequested(const QPoint &)),
|
||||
SLOT(stores_customContextMenuRequested(const QPoint &)));
|
||||
|
||||
actionView = new QAction(tr("&View"), this);
|
||||
connect(actionView, SIGNAL(triggered()), SLOT(view()));
|
||||
actionView->setEnabled(false);
|
||||
}
|
||||
actionView = new QAction(tr("&View"), this);
|
||||
connect(actionView, SIGNAL(triggered()), SLOT(view()));
|
||||
actionView->setEnabled(false);
|
||||
}
|
||||
|
||||
private slots:
|
||||
void ksm_busyStarted()
|
||||
{
|
||||
ui.lb_busy->setText(tr("Looking for devices..."));
|
||||
}
|
||||
private Q_SLOTS:
|
||||
void ksm_busyStarted()
|
||||
{
|
||||
ui.lb_busy->setText(tr("Looking for devices..."));
|
||||
}
|
||||
|
||||
void ksm_busyFinished()
|
||||
{
|
||||
ui.lb_busy->setText("");
|
||||
}
|
||||
void ksm_busyFinished()
|
||||
{
|
||||
ui.lb_busy->setText("");
|
||||
}
|
||||
|
||||
void stores_selectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
|
||||
{
|
||||
Q_UNUSED(deselected);
|
||||
void stores_selectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
|
||||
{
|
||||
Q_UNUSED(deselected);
|
||||
|
||||
KeyStoreItem *i = 0;
|
||||
if(!selected.indexes().isEmpty())
|
||||
{
|
||||
QModelIndex index = selected.indexes().first();
|
||||
i = (KeyStoreItem *)model->itemFromIndex(index);
|
||||
}
|
||||
KeyStoreItem *i = 0;
|
||||
if (!selected.indexes().isEmpty()) {
|
||||
QModelIndex index = selected.indexes().first();
|
||||
i = (KeyStoreItem *)model->itemFromIndex(index);
|
||||
}
|
||||
|
||||
bool viewable = false;
|
||||
bool choosable = false;
|
||||
if(i && i->type() == KeyStoreItem::Entry)
|
||||
{
|
||||
QCA::KeyStoreEntry entry = i->keyStoreEntry;
|
||||
if(entry.type() == QCA::KeyStoreEntry::TypeKeyBundle)
|
||||
{
|
||||
viewable = true;
|
||||
choosable = true;
|
||||
cur_entry = entry;
|
||||
}
|
||||
}
|
||||
bool viewable = false;
|
||||
bool choosable = false;
|
||||
if (i && i->type() == KeyStoreItem::Entry) {
|
||||
QCA::KeyStoreEntry entry = i->keyStoreEntry;
|
||||
if (entry.type() == QCA::KeyStoreEntry::TypeKeyBundle) {
|
||||
viewable = true;
|
||||
choosable = true;
|
||||
cur_entry = entry;
|
||||
}
|
||||
}
|
||||
|
||||
if(!choosable)
|
||||
cur_entry = QCA::KeyStoreEntry();
|
||||
if (!choosable)
|
||||
cur_entry = QCA::KeyStoreEntry();
|
||||
|
||||
actionView->setEnabled(viewable);
|
||||
actionView->setEnabled(viewable);
|
||||
|
||||
QPushButton *ok = ui.buttonBox->button(QDialogButtonBox::Ok);
|
||||
if(choosable && !ok->isEnabled())
|
||||
ok->setEnabled(true);
|
||||
else if(!choosable && ok->isEnabled())
|
||||
ok->setEnabled(false);
|
||||
}
|
||||
QPushButton *ok = ui.buttonBox->button(QDialogButtonBox::Ok);
|
||||
if (choosable && !ok->isEnabled())
|
||||
ok->setEnabled(true);
|
||||
else if (!choosable && ok->isEnabled())
|
||||
ok->setEnabled(false);
|
||||
}
|
||||
|
||||
void stores_customContextMenuRequested(const QPoint &pos)
|
||||
{
|
||||
QItemSelection selection = ui.lv_stores->selectionModel()->selection();
|
||||
if(selection.indexes().isEmpty())
|
||||
return;
|
||||
void stores_customContextMenuRequested(const QPoint &pos)
|
||||
{
|
||||
QItemSelection selection = ui.lv_stores->selectionModel()->selection();
|
||||
if (selection.indexes().isEmpty())
|
||||
return;
|
||||
|
||||
QModelIndex index = selection.indexes().first();
|
||||
KeyStoreItem *i = (KeyStoreItem *)model->itemFromIndex(index);
|
||||
if(i && i->type() == KeyStoreItem::Entry)
|
||||
{
|
||||
QMenu menu(q);
|
||||
menu.addAction(actionView);
|
||||
menu.exec(ui.lv_stores->viewport()->mapToGlobal(pos));
|
||||
}
|
||||
}
|
||||
QModelIndex index = selection.indexes().first();
|
||||
KeyStoreItem *i = (KeyStoreItem *)model->itemFromIndex(index);
|
||||
if (i && i->type() == KeyStoreItem::Entry) {
|
||||
QMenu menu(q);
|
||||
menu.addAction(actionView);
|
||||
menu.exec(ui.lv_stores->viewport()->mapToGlobal(pos));
|
||||
}
|
||||
}
|
||||
|
||||
void view()
|
||||
{
|
||||
emit q->viewCertificate(cur_entry.keyBundle().certificateChain());
|
||||
}
|
||||
void view()
|
||||
{
|
||||
emit q->viewCertificate(cur_entry.keyBundle().certificateChain());
|
||||
}
|
||||
};
|
||||
|
||||
KeySelectDlg::KeySelectDlg(QWidget *parent) :
|
||||
QDialog(parent)
|
||||
KeySelectDlg::KeySelectDlg(QWidget *parent)
|
||||
: QDialog(parent)
|
||||
{
|
||||
d = new Private(this);
|
||||
d = new Private(this);
|
||||
}
|
||||
|
||||
KeySelectDlg::~KeySelectDlg()
|
||||
{
|
||||
delete d;
|
||||
delete d;
|
||||
}
|
||||
|
||||
void KeySelectDlg::setIcon(IconType type, const QPixmap &icon)
|
||||
{
|
||||
d->model->shared.iconset[type] = icon;
|
||||
d->model->shared.iconset[type] = icon;
|
||||
}
|
||||
|
||||
void KeySelectDlg::accept()
|
||||
{
|
||||
QCA::KeyStoreEntry entry = d->cur_entry;
|
||||
QDialog::accept();
|
||||
emit selected(entry);
|
||||
QCA::KeyStoreEntry entry = d->cur_entry;
|
||||
QDialog::accept();
|
||||
emit selected(entry);
|
||||
}
|
||||
|
||||
#include "keyselectdlg.moc"
|
||||
|
@ -26,41 +26,40 @@
|
||||
|
||||
class QPixmap;
|
||||
|
||||
namespace QCA
|
||||
{
|
||||
class CertificateChain;
|
||||
class KeyStoreEntry;
|
||||
namespace QCA {
|
||||
class CertificateChain;
|
||||
class KeyStoreEntry;
|
||||
}
|
||||
|
||||
class KeySelectDlg : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum IconType
|
||||
{
|
||||
IconCert,
|
||||
IconCrl,
|
||||
IconKeyBundle,
|
||||
IconPgpPub,
|
||||
IconPgpSec
|
||||
};
|
||||
enum IconType
|
||||
{
|
||||
IconCert,
|
||||
IconCrl,
|
||||
IconKeyBundle,
|
||||
IconPgpPub,
|
||||
IconPgpSec
|
||||
};
|
||||
|
||||
KeySelectDlg(QWidget *parent = 0);
|
||||
~KeySelectDlg();
|
||||
KeySelectDlg(QWidget *parent = 0);
|
||||
~KeySelectDlg();
|
||||
|
||||
void setIcon(IconType type, const QPixmap &icon);
|
||||
void setIcon(IconType type, const QPixmap &icon);
|
||||
|
||||
signals:
|
||||
void selected(const QCA::KeyStoreEntry &entry);
|
||||
void viewCertificate(const QCA::CertificateChain &chain);
|
||||
Q_SIGNALS:
|
||||
void selected(const QCA::KeyStoreEntry &entry);
|
||||
void viewCertificate(const QCA::CertificateChain &chain);
|
||||
|
||||
protected slots:
|
||||
virtual void accept();
|
||||
virtual void accept();
|
||||
|
||||
private:
|
||||
class Private;
|
||||
friend class Private;
|
||||
Private *d;
|
||||
class Private;
|
||||
friend class Private;
|
||||
Private *d;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -30,18 +30,18 @@
|
||||
class Pkcs11ConfigDlg : public QDialog
|
||||
{
|
||||
public:
|
||||
Pkcs11ConfigDlg(QWidget *parent = 0);
|
||||
Pkcs11ConfigDlg(const QString &providerName, const QVariantMap &config, QWidget *parent = 0);
|
||||
~Pkcs11ConfigDlg();
|
||||
Pkcs11ConfigDlg(QWidget *parent = 0);
|
||||
Pkcs11ConfigDlg(const QString &providerName, const QVariantMap &config, QWidget *parent = 0);
|
||||
~Pkcs11ConfigDlg();
|
||||
|
||||
static bool isSupported();
|
||||
static bool isSupported();
|
||||
|
||||
protected slots:
|
||||
virtual void done(int r);
|
||||
virtual void done(int r);
|
||||
|
||||
private:
|
||||
class Private;
|
||||
Private *d;
|
||||
class Private;
|
||||
Private *d;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -21,301 +21,278 @@
|
||||
|
||||
#include "prompter.h"
|
||||
|
||||
#include <QtCore>
|
||||
#include <QtGui>
|
||||
#include <QtCrypto>
|
||||
#include <QMessageBox>
|
||||
#include <QInputDialog>
|
||||
#include <QApplication>
|
||||
#include <QInputDialog>
|
||||
#include <QMessageBox>
|
||||
#include <QtCore>
|
||||
#include <QtCrypto>
|
||||
#include <QtGui>
|
||||
|
||||
class Prompter::Private : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
public:
|
||||
Prompter *q;
|
||||
Prompter *q;
|
||||
|
||||
class Item
|
||||
{
|
||||
public:
|
||||
int id;
|
||||
QCA::Event event;
|
||||
};
|
||||
class Item
|
||||
{
|
||||
public:
|
||||
int id;
|
||||
QCA::Event event;
|
||||
};
|
||||
|
||||
QCA::EventHandler handler;
|
||||
QList<Item> pending;
|
||||
bool prompting;
|
||||
QMessageBox *token_prompt;
|
||||
bool auto_accept;
|
||||
QCA::EventHandler handler;
|
||||
QList<Item> pending;
|
||||
bool prompting;
|
||||
QMessageBox * token_prompt;
|
||||
bool auto_accept;
|
||||
|
||||
QCA::KeyStoreManager ksm;
|
||||
QList<QCA::KeyStore*> keyStores;
|
||||
QCA::KeyStoreManager ksm;
|
||||
QList<QCA::KeyStore *> keyStores;
|
||||
|
||||
Private(Prompter *_q) :
|
||||
QObject(_q),
|
||||
q(_q),
|
||||
handler(this),
|
||||
prompting(false),
|
||||
token_prompt(0),
|
||||
ksm(this)
|
||||
{
|
||||
connect(&handler, SIGNAL(eventReady(int, const QCA::Event &)), SLOT(ph_eventReady(int, const QCA::Event &)));
|
||||
handler.start();
|
||||
Private(Prompter *_q)
|
||||
: QObject(_q)
|
||||
, q(_q)
|
||||
, handler(this)
|
||||
, prompting(false)
|
||||
, token_prompt(0)
|
||||
, ksm(this)
|
||||
{
|
||||
connect(&handler, SIGNAL(eventReady(int, const QCA::Event &)), SLOT(ph_eventReady(int, const QCA::Event &)));
|
||||
handler.start();
|
||||
|
||||
connect(&ksm, SIGNAL(keyStoreAvailable(const QString &)), SLOT(ks_available(const QString &)));
|
||||
foreach(const QString &keyStoreId, ksm.keyStores())
|
||||
ks_available(keyStoreId);
|
||||
}
|
||||
connect(&ksm, SIGNAL(keyStoreAvailable(const QString &)), SLOT(ks_available(const QString &)));
|
||||
foreach (const QString &keyStoreId, ksm.keyStores())
|
||||
ks_available(keyStoreId);
|
||||
}
|
||||
|
||||
~Private()
|
||||
{
|
||||
qDeleteAll(keyStores);
|
||||
~Private()
|
||||
{
|
||||
qDeleteAll(keyStores);
|
||||
|
||||
while(!pending.isEmpty())
|
||||
handler.reject(pending.takeFirst().id);
|
||||
}
|
||||
while (!pending.isEmpty())
|
||||
handler.reject(pending.takeFirst().id);
|
||||
}
|
||||
|
||||
private slots:
|
||||
void ph_eventReady(int id, const QCA::Event &event)
|
||||
{
|
||||
Item i;
|
||||
i.id = id;
|
||||
i.event = event;
|
||||
pending += i;
|
||||
nextEvent();
|
||||
}
|
||||
private Q_SLOTS:
|
||||
void ph_eventReady(int id, const QCA::Event &event)
|
||||
{
|
||||
Item i;
|
||||
i.id = id;
|
||||
i.event = event;
|
||||
pending += i;
|
||||
nextEvent();
|
||||
}
|
||||
|
||||
void nextEvent()
|
||||
{
|
||||
if(prompting || pending.isEmpty())
|
||||
return;
|
||||
void nextEvent()
|
||||
{
|
||||
if (prompting || pending.isEmpty())
|
||||
return;
|
||||
|
||||
prompting = true;
|
||||
prompting = true;
|
||||
|
||||
const Item &i = pending.first();
|
||||
const int &id = i.id;
|
||||
const QCA::Event &event = i.event;
|
||||
const Item & i = pending.first();
|
||||
const int & id = i.id;
|
||||
const QCA::Event &event = i.event;
|
||||
|
||||
if(event.type() == QCA::Event::Password)
|
||||
{
|
||||
QCA::SecureArray known = q->knownPassword(event);
|
||||
if(!known.isEmpty())
|
||||
{
|
||||
handler.submitPassword(id, known);
|
||||
goto end;
|
||||
}
|
||||
if (event.type() == QCA::Event::Password) {
|
||||
QCA::SecureArray known = q->knownPassword(event);
|
||||
if (!known.isEmpty()) {
|
||||
handler.submitPassword(id, known);
|
||||
goto end;
|
||||
}
|
||||
|
||||
QString type = Prompter::tr("password");
|
||||
if(event.passwordStyle() == QCA::Event::StylePassphrase)
|
||||
type = Prompter::tr("passphrase");
|
||||
else if(event.passwordStyle() == QCA::Event::StylePIN)
|
||||
type = Prompter::tr("PIN");
|
||||
QString type = Prompter::tr("password");
|
||||
if (event.passwordStyle() == QCA::Event::StylePassphrase)
|
||||
type = Prompter::tr("passphrase");
|
||||
else if (event.passwordStyle() == QCA::Event::StylePIN)
|
||||
type = Prompter::tr("PIN");
|
||||
|
||||
QString str;
|
||||
if(event.source() == QCA::Event::KeyStore)
|
||||
{
|
||||
QString name;
|
||||
QCA::KeyStoreEntry entry = event.keyStoreEntry();
|
||||
if(!entry.isNull())
|
||||
{
|
||||
name = entry.name();
|
||||
}
|
||||
else
|
||||
{
|
||||
if(event.keyStoreInfo().type() == QCA::KeyStore::SmartCard)
|
||||
name = Prompter::tr("the '%1' token").arg(event.keyStoreInfo().name());
|
||||
else
|
||||
name = event.keyStoreInfo().name();
|
||||
}
|
||||
str = Prompter::tr("Enter %1 for %2").arg(type, name);
|
||||
}
|
||||
else if(!event.fileName().isEmpty())
|
||||
{
|
||||
QFileInfo fi(event.fileName());
|
||||
str = Prompter::tr("Enter %1 for %2:").arg(type, fi.fileName());
|
||||
}
|
||||
else
|
||||
str = Prompter::tr("Enter %1:").arg(type);
|
||||
QString str;
|
||||
if (event.source() == QCA::Event::KeyStore) {
|
||||
QString name;
|
||||
QCA::KeyStoreEntry entry = event.keyStoreEntry();
|
||||
if (!entry.isNull()) {
|
||||
name = entry.name();
|
||||
} else {
|
||||
if (event.keyStoreInfo().type() == QCA::KeyStore::SmartCard)
|
||||
name = Prompter::tr("the '%1' token").arg(event.keyStoreInfo().name());
|
||||
else
|
||||
name = event.keyStoreInfo().name();
|
||||
}
|
||||
str = Prompter::tr("Enter %1 for %2").arg(type, name);
|
||||
} else if (!event.fileName().isEmpty()) {
|
||||
QFileInfo fi(event.fileName());
|
||||
str = Prompter::tr("Enter %1 for %2:").arg(type, fi.fileName());
|
||||
} else
|
||||
str = Prompter::tr("Enter %1:").arg(type);
|
||||
|
||||
bool ok;
|
||||
QString pass = QInputDialog::getText(0, QApplication::instance()->applicationName() + ": " + tr("Prompt"), str, QLineEdit::Password, QString(), &ok);
|
||||
if(ok)
|
||||
{
|
||||
QCA::SecureArray password = pass.toUtf8();
|
||||
q->userSubmitted(password, event);
|
||||
handler.submitPassword(id, password);
|
||||
}
|
||||
else
|
||||
handler.reject(id);
|
||||
}
|
||||
else if(event.type() == QCA::Event::Token)
|
||||
{
|
||||
// even though we're being prompted for a missing token,
|
||||
// we should still check if the token is present, due to
|
||||
// a possible race between insert and token request.
|
||||
bool found = false;
|
||||
bool ok;
|
||||
QString pass = QInputDialog::getText(0,
|
||||
QApplication::instance()->applicationName() + ": " + tr("Prompt"),
|
||||
str,
|
||||
QLineEdit::Password,
|
||||
QString(),
|
||||
&ok);
|
||||
if (ok) {
|
||||
QCA::SecureArray password = pass.toUtf8();
|
||||
q->userSubmitted(password, event);
|
||||
handler.submitPassword(id, password);
|
||||
} else
|
||||
handler.reject(id);
|
||||
} else if (event.type() == QCA::Event::Token) {
|
||||
// even though we're being prompted for a missing token,
|
||||
// we should still check if the token is present, due to
|
||||
// a possible race between insert and token request.
|
||||
bool found = false;
|
||||
|
||||
// token-only
|
||||
if(event.keyStoreEntry().isNull())
|
||||
{
|
||||
foreach(QCA::KeyStore *ks, keyStores)
|
||||
{
|
||||
if(ks->id() == event.keyStoreInfo().id())
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// token-entry
|
||||
else
|
||||
{
|
||||
QCA::KeyStoreEntry kse = event.keyStoreEntry();
|
||||
// token-only
|
||||
if (event.keyStoreEntry().isNull()) {
|
||||
foreach (QCA::KeyStore *ks, keyStores) {
|
||||
if (ks->id() == event.keyStoreInfo().id()) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// token-entry
|
||||
else {
|
||||
QCA::KeyStoreEntry kse = event.keyStoreEntry();
|
||||
|
||||
QCA::KeyStore *ks = 0;
|
||||
foreach(QCA::KeyStore *i, keyStores)
|
||||
{
|
||||
if(i->id() == event.keyStoreInfo().id())
|
||||
{
|
||||
ks = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(ks)
|
||||
{
|
||||
QList<QCA::KeyStoreEntry> list = ks->entryList();
|
||||
foreach(const QCA::KeyStoreEntry &e, list)
|
||||
{
|
||||
if(e.id() == kse.id() && kse.isAvailable())
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(found)
|
||||
{
|
||||
// auto-accept
|
||||
handler.tokenOkay(id);
|
||||
return;
|
||||
}
|
||||
QCA::KeyStore *ks = 0;
|
||||
foreach (QCA::KeyStore *i, keyStores) {
|
||||
if (i->id() == event.keyStoreInfo().id()) {
|
||||
ks = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ks) {
|
||||
QList<QCA::KeyStoreEntry> list = ks->entryList();
|
||||
foreach (const QCA::KeyStoreEntry &e, list) {
|
||||
if (e.id() == kse.id() && kse.isAvailable()) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (found) {
|
||||
// auto-accept
|
||||
handler.tokenOkay(id);
|
||||
return;
|
||||
}
|
||||
|
||||
QCA::KeyStoreEntry entry = event.keyStoreEntry();
|
||||
QString name;
|
||||
if(!entry.isNull())
|
||||
{
|
||||
name = Prompter::tr("Please make %1 (of %2) available").arg(entry.name(), entry.storeName());
|
||||
}
|
||||
else
|
||||
{
|
||||
name = Prompter::tr("Please insert the '%1' token").arg(event.keyStoreInfo().name());
|
||||
}
|
||||
QCA::KeyStoreEntry entry = event.keyStoreEntry();
|
||||
QString name;
|
||||
if (!entry.isNull()) {
|
||||
name = Prompter::tr("Please make %1 (of %2) available").arg(entry.name(), entry.storeName());
|
||||
} else {
|
||||
name = Prompter::tr("Please insert the '%1' token").arg(event.keyStoreInfo().name());
|
||||
}
|
||||
|
||||
QString str = Prompter::tr("%1 and click OK.").arg(name);
|
||||
QString str = Prompter::tr("%1 and click OK.").arg(name);
|
||||
|
||||
QMessageBox msgBox(QMessageBox::Information, QApplication::instance()->applicationName() + ": " + tr("Prompt"), str, QMessageBox::Ok | QMessageBox::Cancel, 0);
|
||||
token_prompt = &msgBox;
|
||||
auto_accept = false;
|
||||
if(msgBox.exec() == QMessageBox::Ok || auto_accept)
|
||||
handler.tokenOkay(id);
|
||||
else
|
||||
handler.reject(id);
|
||||
token_prompt = 0;
|
||||
}
|
||||
else
|
||||
handler.reject(id);
|
||||
QMessageBox msgBox(QMessageBox::Information,
|
||||
QApplication::instance()->applicationName() + ": " + tr("Prompt"),
|
||||
str,
|
||||
QMessageBox::Ok | QMessageBox::Cancel,
|
||||
0);
|
||||
token_prompt = &msgBox;
|
||||
auto_accept = false;
|
||||
if (msgBox.exec() == QMessageBox::Ok || auto_accept)
|
||||
handler.tokenOkay(id);
|
||||
else
|
||||
handler.reject(id);
|
||||
token_prompt = 0;
|
||||
} else
|
||||
handler.reject(id);
|
||||
|
||||
end:
|
||||
pending.removeFirst();
|
||||
prompting = false;
|
||||
end:
|
||||
pending.removeFirst();
|
||||
prompting = false;
|
||||
|
||||
if(!pending.isEmpty())
|
||||
QMetaObject::invokeMethod(this, "nextEvent", Qt::QueuedConnection);
|
||||
}
|
||||
if (!pending.isEmpty())
|
||||
QMetaObject::invokeMethod(this, "nextEvent", Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
void ks_available(const QString &keyStoreId)
|
||||
{
|
||||
QCA::KeyStore *ks = new QCA::KeyStore(keyStoreId, &ksm);
|
||||
connect(ks, SIGNAL(updated()), SLOT(ks_updated()));
|
||||
connect(ks, SIGNAL(unavailable()), SLOT(ks_unavailable()));
|
||||
keyStores += ks;
|
||||
ks->startAsynchronousMode();
|
||||
void ks_available(const QString &keyStoreId)
|
||||
{
|
||||
QCA::KeyStore *ks = new QCA::KeyStore(keyStoreId, &ksm);
|
||||
connect(ks, SIGNAL(updated()), SLOT(ks_updated()));
|
||||
connect(ks, SIGNAL(unavailable()), SLOT(ks_unavailable()));
|
||||
keyStores += ks;
|
||||
ks->startAsynchronousMode();
|
||||
|
||||
// are we currently in a token-only prompt?
|
||||
if(token_prompt && pending.first().event.type() == QCA::Event::Token && pending.first().event.keyStoreEntry().isNull())
|
||||
{
|
||||
// was the token we're looking for just inserted?
|
||||
if(pending.first().event.keyStoreInfo().id() == keyStoreId)
|
||||
{
|
||||
// auto-accept
|
||||
auto_accept = true;
|
||||
token_prompt->accept();
|
||||
}
|
||||
}
|
||||
}
|
||||
// are we currently in a token-only prompt?
|
||||
if (token_prompt && pending.first().event.type() == QCA::Event::Token &&
|
||||
pending.first().event.keyStoreEntry().isNull()) {
|
||||
// was the token we're looking for just inserted?
|
||||
if (pending.first().event.keyStoreInfo().id() == keyStoreId) {
|
||||
// auto-accept
|
||||
auto_accept = true;
|
||||
token_prompt->accept();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ks_unavailable()
|
||||
{
|
||||
QCA::KeyStore *ks = (QCA::KeyStore *)sender();
|
||||
keyStores.removeAll(ks);
|
||||
delete ks;
|
||||
}
|
||||
void ks_unavailable()
|
||||
{
|
||||
QCA::KeyStore *ks = (QCA::KeyStore *)sender();
|
||||
keyStores.removeAll(ks);
|
||||
delete ks;
|
||||
}
|
||||
|
||||
void ks_updated()
|
||||
{
|
||||
QCA::KeyStore *ks = (QCA::KeyStore *)sender();
|
||||
void ks_updated()
|
||||
{
|
||||
QCA::KeyStore *ks = (QCA::KeyStore *)sender();
|
||||
|
||||
// are we currently in a token-entry prompt?
|
||||
if(token_prompt && pending.first().event.type() == QCA::Event::Token && !pending.first().event.keyStoreEntry().isNull())
|
||||
{
|
||||
QCA::KeyStoreEntry kse = pending.first().event.keyStoreEntry();
|
||||
// are we currently in a token-entry prompt?
|
||||
if (token_prompt && pending.first().event.type() == QCA::Event::Token &&
|
||||
!pending.first().event.keyStoreEntry().isNull()) {
|
||||
QCA::KeyStoreEntry kse = pending.first().event.keyStoreEntry();
|
||||
|
||||
// was the token of the entry we're looking for updated?
|
||||
if(pending.first().event.keyStoreInfo().id() == ks->id())
|
||||
{
|
||||
// is the entry available?
|
||||
bool avail = false;
|
||||
QList<QCA::KeyStoreEntry> list = ks->entryList();
|
||||
foreach(const QCA::KeyStoreEntry &e, list)
|
||||
{
|
||||
if(e.id() == kse.id())
|
||||
{
|
||||
avail = kse.isAvailable();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(avail)
|
||||
{
|
||||
// auto-accept
|
||||
auto_accept = true;
|
||||
token_prompt->accept();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// was the token of the entry we're looking for updated?
|
||||
if (pending.first().event.keyStoreInfo().id() == ks->id()) {
|
||||
// is the entry available?
|
||||
bool avail = false;
|
||||
QList<QCA::KeyStoreEntry> list = ks->entryList();
|
||||
foreach (const QCA::KeyStoreEntry &e, list) {
|
||||
if (e.id() == kse.id()) {
|
||||
avail = kse.isAvailable();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (avail) {
|
||||
// auto-accept
|
||||
auto_accept = true;
|
||||
token_prompt->accept();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Prompter::Prompter(QObject *parent) :
|
||||
QObject(parent)
|
||||
Prompter::Prompter(QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
d = new Private(this);
|
||||
d = new Private(this);
|
||||
}
|
||||
|
||||
Prompter::~Prompter()
|
||||
{
|
||||
delete d;
|
||||
delete d;
|
||||
}
|
||||
|
||||
QCA::SecureArray Prompter::knownPassword(const QCA::Event &event)
|
||||
{
|
||||
Q_UNUSED(event);
|
||||
return QCA::SecureArray();
|
||||
Q_UNUSED(event);
|
||||
return QCA::SecureArray();
|
||||
}
|
||||
|
||||
void Prompter::userSubmitted(const QCA::SecureArray &password, const QCA::Event &event)
|
||||
{
|
||||
Q_UNUSED(password);
|
||||
Q_UNUSED(event);
|
||||
Q_UNUSED(password);
|
||||
Q_UNUSED(event);
|
||||
}
|
||||
|
||||
#include "prompter.moc"
|
||||
|
@ -24,34 +24,33 @@
|
||||
|
||||
#include <QObject>
|
||||
|
||||
namespace QCA
|
||||
{
|
||||
class SecureArray;
|
||||
class Event;
|
||||
namespace QCA {
|
||||
class SecureArray;
|
||||
class Event;
|
||||
}
|
||||
|
||||
class Prompter : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
public:
|
||||
Prompter(QObject *parent = 0);
|
||||
~Prompter();
|
||||
Prompter(QObject *parent = nullptr);
|
||||
~Prompter();
|
||||
|
||||
protected:
|
||||
// called with every password event, to check for a known value.
|
||||
// reimplement it to provide known/cached passwords.
|
||||
virtual QCA::SecureArray knownPassword(const QCA::Event &event);
|
||||
// called with every password event, to check for a known value.
|
||||
// reimplement it to provide known/cached passwords.
|
||||
virtual QCA::SecureArray knownPassword(const QCA::Event &event);
|
||||
|
||||
// called when a user-entered password is submitted. note that this
|
||||
// does not mean the password was correct. to know if the password
|
||||
// was correct, you'll have to match up the event information with
|
||||
// the operation that triggered it.
|
||||
virtual void userSubmitted(const QCA::SecureArray &password, const QCA::Event &event);
|
||||
// called when a user-entered password is submitted. note that this
|
||||
// does not mean the password was correct. to know if the password
|
||||
// was correct, you'll have to match up the event information with
|
||||
// the operation that triggered it.
|
||||
virtual void userSubmitted(const QCA::SecureArray &password, const QCA::Event &event);
|
||||
|
||||
private:
|
||||
class Private;
|
||||
friend class Private;
|
||||
Private *d;
|
||||
class Private;
|
||||
friend class Private;
|
||||
Private *d;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -1,7 +1,5 @@
|
||||
set(eventhandlerdemo_bin_SRCS eventhandlerdemo.cpp)
|
||||
|
||||
MY_AUTOMOC( eventhandlerdemo_bin_SRCS)
|
||||
|
||||
add_executable(eventhandlerdemo ${eventhandlerdemo_bin_SRCS})
|
||||
|
||||
target_link_qca_libraries(eventhandlerdemo)
|
||||
|
@ -33,77 +33,77 @@
|
||||
/**
|
||||
We need a class on the client side to handle password requests.
|
||||
*/
|
||||
class ClientPassphraseHandler: public QObject
|
||||
class ClientPassphraseHandler : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ClientPassphraseHandler(QObject *parent = 0) : QObject( parent )
|
||||
ClientPassphraseHandler(QObject *parent = nullptr)
|
||||
: QObject(parent)
|
||||
{
|
||||
// When the PasswordAsker or TokenAsker needs to interact
|
||||
// with the user, it raises a signal. We connect that to a
|
||||
// local slot to get the required information.
|
||||
connect( &m_handler, SIGNAL( eventReady(int, const QCA::Event &) ),
|
||||
SLOT( my_eventReady(int, const QCA::Event &) ) );
|
||||
connect(&m_handler, &QCA::EventHandler::eventReady, this, &ClientPassphraseHandler::my_eventReady);
|
||||
|
||||
// Now that we are set up, we can start the EventHandler. Nothing
|
||||
// will happen if you don't call this method.
|
||||
m_handler.start();
|
||||
}
|
||||
|
||||
private slots:
|
||||
private Q_SLOTS:
|
||||
// This slot gets called when the provider needs a token inserted,
|
||||
// or to get a passphrase / password / PIN.
|
||||
void my_eventReady(int id, const QCA::Event &event)
|
||||
{
|
||||
// We can sanity check the event
|
||||
if ( event.isNull() ) {
|
||||
if (event.isNull()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Events can be associated with a a keystore or a file/bytearray
|
||||
// You can tell which by looking at the Source
|
||||
if ( event.source() == QCA::Event::KeyStore ) {
|
||||
if (event.source() == QCA::Event::KeyStore) {
|
||||
std::cout << "Event is associated with a key store operation" << std::endl;
|
||||
} else if ( event.source() == QCA::Event::Data ) {
|
||||
} else if (event.source() == QCA::Event::Data) {
|
||||
std::cout << "Event is associated with a file or some other data" << std::endl;
|
||||
// if the event comes from a file type operation, you can get the
|
||||
// name / label using fileName()
|
||||
std::cout << " Filename: " << qPrintable( event.fileName() ) << std::endl;
|
||||
std::cout << " Filename: " << qPrintable(event.fileName()) << std::endl;
|
||||
} else {
|
||||
std::cout << "Unexpected Source for Event" << std::endl;
|
||||
}
|
||||
|
||||
// There are different kinds of events.
|
||||
if ( event.type() == QCA::Event::Token ) {
|
||||
if (event.type() == QCA::Event::Token) {
|
||||
// You would typically ask the user to insert the token here
|
||||
std::cout << "Request for token" << std::endl;
|
||||
// we just fake it for this demo.
|
||||
m_handler.tokenOkay( id );
|
||||
m_handler.tokenOkay(id);
|
||||
// you could use m_handler.reject( id ) to refuse the token request
|
||||
|
||||
} else if ( event.type() == QCA::Event::Password ) {
|
||||
} else if (event.type() == QCA::Event::Password) {
|
||||
std::cout << "Request for password, passphrase or PIN" << std::endl;
|
||||
// and within the Password type, we have a few different styles.
|
||||
if ( event.passwordStyle() == QCA::Event::StylePassword ) {
|
||||
if (event.passwordStyle() == QCA::Event::StylePassword) {
|
||||
std::cout << " [Password request]" << std::endl;
|
||||
} else if ( event.passwordStyle() == QCA::Event::StylePassphrase ) {
|
||||
} else if (event.passwordStyle() == QCA::Event::StylePassphrase) {
|
||||
std::cout << " [Passphrase request]" << std::endl;
|
||||
} else if ( event.passwordStyle() == QCA::Event::StylePIN ){
|
||||
} else if (event.passwordStyle() == QCA::Event::StylePIN) {
|
||||
std::cout << " [PIN request]" << std::endl;
|
||||
} else {
|
||||
std::cout << " [unexpect request style]" << std::endl;
|
||||
}
|
||||
// You would typically request the password/PIN/passphrase.
|
||||
// again, we just fake it.
|
||||
m_handler.submitPassword( id, QCA::SecureArray( "hello" ) );
|
||||
m_handler.submitPassword(id, QCA::SecureArray("hello"));
|
||||
|
||||
} else {
|
||||
std::cout << "Unexpected event type" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
QCA::EventHandler m_handler;
|
||||
|
||||
};
|
||||
|
||||
void asker_procedure();
|
||||
@ -112,7 +112,7 @@ class AskerThread : public QThread
|
||||
{
|
||||
Q_OBJECT
|
||||
protected:
|
||||
virtual void run()
|
||||
void run() override
|
||||
{
|
||||
asker_procedure();
|
||||
}
|
||||
@ -130,7 +130,7 @@ int main(int argc, char **argv)
|
||||
|
||||
// handler and asker cannot occur in the same thread
|
||||
AskerThread askerThread;
|
||||
QObject::connect(&askerThread, SIGNAL(finished()), &exampleApp, SLOT(quit()));
|
||||
QObject::connect(&askerThread, &AskerThread::finished, &exampleApp, &QCoreApplication::quit);
|
||||
askerThread.start();
|
||||
|
||||
exampleApp.exec();
|
||||
@ -141,7 +141,7 @@ void asker_procedure()
|
||||
{
|
||||
QCA::PasswordAsker pwAsker;
|
||||
|
||||
pwAsker.ask( QCA::Event::StylePassword, "foo.tmp", 0 );
|
||||
pwAsker.ask(QCA::Event::StylePassword, QStringLiteral("foo.tmp"), nullptr);
|
||||
|
||||
pwAsker.waitForResponse();
|
||||
|
||||
@ -151,11 +151,14 @@ void asker_procedure()
|
||||
|
||||
QCA::TokenAsker tokenAsker;
|
||||
|
||||
tokenAsker.ask( QCA::KeyStoreInfo( QCA::KeyStore::SmartCard, "Token Id", "Token Name" ), QCA::KeyStoreEntry(), 0 );
|
||||
tokenAsker.ask(
|
||||
QCA::KeyStoreInfo(QCA::KeyStore::SmartCard, QStringLiteral("Token Id"), QStringLiteral("Token Name")),
|
||||
QCA::KeyStoreEntry(),
|
||||
nullptr);
|
||||
|
||||
tokenAsker.waitForResponse();
|
||||
|
||||
if ( tokenAsker.accepted() ) {
|
||||
if (tokenAsker.accepted()) {
|
||||
std::cout << "Token was accepted" << std::endl;
|
||||
} else {
|
||||
std::cout << "Token was not accepted" << std::endl;
|
||||
|
@ -169,7 +169,7 @@ The code below shows how to create an SSL client
|
||||
|
||||
*/
|
||||
|
||||
/* \example tlssocket.cpp
|
||||
/** \example tlssocket.cpp
|
||||
|
||||
The code below shows how to create a socket that can operate
|
||||
over an Transport Layer Security (TLS, also known as SSL) connection.
|
||||
|
@ -24,7 +24,7 @@
|
||||
|
||||
#include <QCoreApplication>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <cstdio>
|
||||
|
||||
#ifdef QT_STATICPLUGIN
|
||||
#include "import_plugins.h"
|
||||
@ -32,47 +32,46 @@
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
// the Initializer object sets things up, and
|
||||
// also does cleanup when it goes out of scope
|
||||
QCA::Initializer init;
|
||||
// the Initializer object sets things up, and
|
||||
// also does cleanup when it goes out of scope
|
||||
QCA::Initializer init;
|
||||
|
||||
QCoreApplication app(argc, argv);
|
||||
QCoreApplication app(argc, argv);
|
||||
|
||||
// we use the first argument if provided, or
|
||||
// use "hello" if no arguments
|
||||
QCA::SecureArray arg = (argc >= 2) ? argv[1] : "hello";
|
||||
// we use the first argument if provided, or
|
||||
// use "hello" if no arguments
|
||||
QCA::SecureArray arg = (argc >= 2) ? argv[1] : "hello";
|
||||
|
||||
// must always check that an algorithm is supported before using it
|
||||
if( !QCA::isSupported("sha1") )
|
||||
printf("SHA1 not supported!\n");
|
||||
else {
|
||||
// this shows the "all in one" approach
|
||||
QString result = QCA::Hash("sha1").hashToString(arg);
|
||||
printf("sha1(\"%s\") = [%s]\n", arg.data(), qPrintable(result));
|
||||
}
|
||||
// must always check that an algorithm is supported before using it
|
||||
if (!QCA::isSupported("sha1"))
|
||||
printf("SHA1 not supported!\n");
|
||||
else {
|
||||
// this shows the "all in one" approach
|
||||
QString result = QCA::Hash(QStringLiteral("sha1")).hashToString(arg);
|
||||
printf("sha1(\"%s\") = [%s]\n", arg.data(), qPrintable(result));
|
||||
}
|
||||
|
||||
// must always check that an algorithm is supported before using it
|
||||
if( !QCA::isSupported("md5") )
|
||||
printf("MD5 not supported!\n");
|
||||
else {
|
||||
// this shows the incremental approach. Naturally
|
||||
// for this simple job, we could use the "all in one"
|
||||
// approach - this is an example, after all :-)
|
||||
QCA::SecureArray part1(arg.toByteArray().left(3)); // three chars - "hel"
|
||||
QCA::SecureArray part2(arg.toByteArray().mid(3)); // the rest - "lo"
|
||||
// must always check that an algorithm is supported before using it
|
||||
if (!QCA::isSupported("md5"))
|
||||
printf("MD5 not supported!\n");
|
||||
else {
|
||||
// this shows the incremental approach. Naturally
|
||||
// for this simple job, we could use the "all in one"
|
||||
// approach - this is an example, after all :-)
|
||||
QCA::SecureArray part1(arg.toByteArray().left(3)); // three chars - "hel"
|
||||
QCA::SecureArray part2(arg.toByteArray().mid(3)); // the rest - "lo"
|
||||
|
||||
// create the required object.
|
||||
QCA::Hash hashObject("md5");
|
||||
// we split it into two parts to show incremental update
|
||||
hashObject.update(part1);
|
||||
hashObject.update(part2);
|
||||
// no more updates after calling final.
|
||||
QCA::SecureArray resultArray = hashObject.final();
|
||||
// convert the result into printable hexadecimal.
|
||||
QString result = QCA::arrayToHex(resultArray.toByteArray());
|
||||
printf("md5(\"%s\") = [%s]\n", arg.data(), qPrintable(result));
|
||||
}
|
||||
// create the required object.
|
||||
QCA::Hash hashObject(QStringLiteral("md5"));
|
||||
// we split it into two parts to show incremental update
|
||||
hashObject.update(part1);
|
||||
hashObject.update(part2);
|
||||
// no more updates after calling final.
|
||||
QCA::SecureArray resultArray = hashObject.final();
|
||||
// convert the result into printable hexadecimal.
|
||||
QString result = QCA::arrayToHex(resultArray.toByteArray());
|
||||
printf("md5(\"%s\") = [%s]\n", arg.data(), qPrintable(result));
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -32,39 +32,38 @@
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
// the Initializer object sets things up, and
|
||||
// also does cleanup when it goes out of scope
|
||||
QCA::Initializer init;
|
||||
// the Initializer object sets things up, and
|
||||
// also does cleanup when it goes out of scope
|
||||
QCA::Initializer init;
|
||||
|
||||
QCoreApplication app(argc, argv);
|
||||
QCoreApplication app(argc, argv);
|
||||
|
||||
// we use the first argument as the data to encode / decode
|
||||
// if an argument is provided. Use "hello" if no argument
|
||||
QByteArray arg; // empty array
|
||||
arg.append((argc >= 2) ? argv[1] : "hello");
|
||||
// we use the first argument as the data to encode / decode
|
||||
// if an argument is provided. Use "hello" if no argument
|
||||
QByteArray arg; // empty array
|
||||
arg.append((argc >= 2) ? argv[1] : "hello");
|
||||
|
||||
// create our object, which does encoding by default
|
||||
// QCA::Hex encoder(QCA::Encode); is equivalent
|
||||
QCA::Hex encoder;
|
||||
// create our object, which does encoding by default
|
||||
// QCA::Hex encoder(QCA::Encode); is equivalent
|
||||
QCA::Hex encoder;
|
||||
|
||||
// You might prefer to use encoder.encode(); and have
|
||||
// it return a QCA::SecureArray, depending on your needs
|
||||
QString encoded = encoder.arrayToString(arg);
|
||||
// You might prefer to use encoder.encode(); and have
|
||||
// it return a QCA::SecureArray, depending on your needs
|
||||
QString encoded = encoder.arrayToString(arg);
|
||||
|
||||
std::cout << arg.data() << " in hex encoding is ";
|
||||
std::cout << encoded.toLatin1().data() << std::endl;
|
||||
std::cout << arg.data() << " in hex encoding is ";
|
||||
std::cout << encoded.toLatin1().data() << std::endl;
|
||||
|
||||
// This time, we'll create an object to decode hexadecimal.
|
||||
// We could also have reused the existing object, calling
|
||||
// clear(); and setup(QCA::Decode); on it.
|
||||
QCA::Hex decoder(QCA::Decode);
|
||||
// This time, we'll create an object to decode hexadecimal.
|
||||
// We could also have reused the existing object, calling
|
||||
// clear(); and setup(QCA::Decode); on it.
|
||||
QCA::Hex decoder(QCA::Decode);
|
||||
|
||||
// This time, we convert a QString into a QString
|
||||
QString decoded = decoder.decodeString(encoded);
|
||||
// This time, we convert a QString into a QString
|
||||
QString decoded = decoder.decodeString(encoded);
|
||||
|
||||
std::cout << encoded.toLatin1().data() << " decoded from hex is ";
|
||||
std::cout << decoded.toLatin1().data() << std::endl;
|
||||
std::cout << encoded.toLatin1().data() << " decoded from hex is ";
|
||||
std::cout << decoded.toLatin1().data() << std::endl;
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,5 @@
|
||||
set(keyloader_bin_SRCS keyloader.cpp)
|
||||
|
||||
MY_AUTOMOC( keyloader_bin_SRCS )
|
||||
|
||||
add_executable(keyloader ${keyloader_bin_SRCS})
|
||||
|
||||
target_link_qca_libraries(keyloader)
|
||||
|
@ -23,98 +23,94 @@
|
||||
#include <QtCrypto>
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QFile>
|
||||
#include <QTimer>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <cstdio>
|
||||
|
||||
#ifdef QT_STATICPLUGIN
|
||||
#include "import_plugins.h"
|
||||
#endif
|
||||
|
||||
class PassphraseHandler: public QObject
|
||||
class PassphraseHandler : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
public:
|
||||
QCA::EventHandler handler;
|
||||
QCA::EventHandler handler;
|
||||
|
||||
PassphraseHandler(QObject *parent = 0) : QObject(parent)
|
||||
{
|
||||
connect(&handler, SIGNAL(eventReady(int, const QCA::Event &)),
|
||||
SLOT(eh_eventReady(int, const QCA::Event &)));
|
||||
handler.start();
|
||||
}
|
||||
PassphraseHandler(QObject *parent = nullptr)
|
||||
: QObject(parent)
|
||||
{
|
||||
connect(&handler, &QCA::EventHandler::eventReady, this, &PassphraseHandler::eh_eventReady);
|
||||
handler.start();
|
||||
}
|
||||
|
||||
private slots:
|
||||
void eh_eventReady(int id, const QCA::Event &event)
|
||||
{
|
||||
if(event.type() == QCA::Event::Password)
|
||||
{
|
||||
QCA::SecureArray pass;
|
||||
QCA::ConsolePrompt prompt;
|
||||
prompt.getHidden("Passphrase");
|
||||
prompt.waitForFinished();
|
||||
pass = prompt.result();
|
||||
handler.submitPassword(id, pass);
|
||||
}
|
||||
else
|
||||
handler.reject(id);
|
||||
}
|
||||
private Q_SLOTS:
|
||||
void eh_eventReady(int id, const QCA::Event &event)
|
||||
{
|
||||
if (event.type() == QCA::Event::Password) {
|
||||
QCA::SecureArray pass;
|
||||
QCA::ConsolePrompt prompt;
|
||||
prompt.getHidden(QStringLiteral("Passphrase"));
|
||||
prompt.waitForFinished();
|
||||
pass = prompt.result();
|
||||
handler.submitPassword(id, pass);
|
||||
} else
|
||||
handler.reject(id);
|
||||
}
|
||||
};
|
||||
|
||||
class App : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
public:
|
||||
QCA::KeyLoader keyLoader;
|
||||
QString str;
|
||||
QCA::KeyLoader keyLoader;
|
||||
QString str;
|
||||
|
||||
App()
|
||||
{
|
||||
connect(&keyLoader, SIGNAL(finished()), SLOT(kl_finished()));
|
||||
}
|
||||
App()
|
||||
{
|
||||
connect(&keyLoader, &QCA::KeyLoader::finished, this, &App::kl_finished);
|
||||
}
|
||||
|
||||
public slots:
|
||||
void start()
|
||||
{
|
||||
keyLoader.loadPrivateKeyFromPEMFile(str);
|
||||
}
|
||||
public Q_SLOTS:
|
||||
void start()
|
||||
{
|
||||
keyLoader.loadPrivateKeyFromPEMFile(str);
|
||||
}
|
||||
|
||||
signals:
|
||||
void quit();
|
||||
Q_SIGNALS:
|
||||
void quit();
|
||||
|
||||
private slots:
|
||||
void kl_finished()
|
||||
{
|
||||
if(keyLoader.convertResult() == QCA::ConvertGood)
|
||||
{
|
||||
QCA::PrivateKey key = keyLoader.privateKey();
|
||||
printf("Loaded successfully. Bits: %d\n", key.bitSize());
|
||||
}
|
||||
else
|
||||
printf("Unable to load.\n");
|
||||
private Q_SLOTS:
|
||||
void kl_finished()
|
||||
{
|
||||
if (keyLoader.convertResult() == QCA::ConvertGood) {
|
||||
QCA::PrivateKey key = keyLoader.privateKey();
|
||||
printf("Loaded successfully. Bits: %d\n", key.bitSize());
|
||||
} else
|
||||
printf("Unable to load.\n");
|
||||
|
||||
emit quit();
|
||||
}
|
||||
emit quit();
|
||||
}
|
||||
};
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
QCA::Initializer init;
|
||||
QCoreApplication qapp(argc, argv);
|
||||
QCA::Initializer init;
|
||||
QCoreApplication qapp(argc, argv);
|
||||
|
||||
if(argc < 2)
|
||||
{
|
||||
printf("usage: keyloader [privatekey.pem]\n");
|
||||
return 0;
|
||||
}
|
||||
if (argc < 2) {
|
||||
printf("usage: keyloader [privatekey.pem]\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
PassphraseHandler passphraseHandler;
|
||||
App app;
|
||||
app.str = argv[1];
|
||||
QObject::connect(&app, SIGNAL(quit()), &qapp, SLOT(quit()));
|
||||
QTimer::singleShot(0, &app, SLOT(start()));
|
||||
qapp.exec();
|
||||
return 0;
|
||||
PassphraseHandler passphraseHandler;
|
||||
App app;
|
||||
app.str = QFile::decodeName(argv[1]);
|
||||
QObject::connect(&app, &App::quit, &qapp, QCoreApplication::quit);
|
||||
QTimer::singleShot(0, &app, &App::start);
|
||||
qapp.exec();
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include "keyloader.moc"
|
||||
|
@ -26,7 +26,7 @@
|
||||
#include <QDebug>
|
||||
|
||||
// needed for printf
|
||||
#include<stdio.h>
|
||||
#include <cstdio>
|
||||
|
||||
#ifdef QT_STATICPLUGIN
|
||||
#include "import_plugins.h"
|
||||
@ -34,53 +34,52 @@
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
// the Initializer object sets things up, and
|
||||
// also does cleanup when it goes out of scope
|
||||
QCA::Initializer init;
|
||||
// the Initializer object sets things up, and
|
||||
// also does cleanup when it goes out of scope
|
||||
QCA::Initializer init;
|
||||
|
||||
QCoreApplication app(argc, argv);
|
||||
QCoreApplication app(argc, argv);
|
||||
|
||||
qDebug() << "This example shows hashed MAC";
|
||||
qDebug() << "This example shows hashed MAC";
|
||||
|
||||
// we use the first argument as the data to authenticate
|
||||
// if an argument is provided. Use "hello" if no argument
|
||||
QByteArray arg = (argc >= 2) ? argv[1] : "hello";
|
||||
// we use the first argument as the data to authenticate
|
||||
// if an argument is provided. Use "hello" if no argument
|
||||
QByteArray arg = (argc >= 2) ? argv[1] : "hello";
|
||||
|
||||
// we use the second argument as the key to authenticate
|
||||
// with, if two arguments are provided. Use "secret" as
|
||||
// the key if less than two arguments.
|
||||
QCA::SecureArray key((argc >= 3) ? argv[2] : "secret");
|
||||
// we use the second argument as the key to authenticate
|
||||
// with, if two arguments are provided. Use "secret" as
|
||||
// the key if less than two arguments.
|
||||
QCA::SecureArray key((argc >= 3) ? argv[2] : "secret");
|
||||
|
||||
// must always check that an algorithm is supported before using it
|
||||
if( !QCA::isSupported("hmac(sha1)") ) {
|
||||
printf("HMAC(SHA1) not supported!\n");
|
||||
} else {
|
||||
// create the required object using HMAC with SHA-1, and an
|
||||
// empty key.
|
||||
QCA::MessageAuthenticationCode hmacObject( "hmac(sha1)", QCA::SecureArray() );
|
||||
// must always check that an algorithm is supported before using it
|
||||
if (!QCA::isSupported("hmac(sha1)")) {
|
||||
printf("HMAC(SHA1) not supported!\n");
|
||||
} else {
|
||||
// create the required object using HMAC with SHA-1, and an
|
||||
// empty key.
|
||||
QCA::MessageAuthenticationCode hmacObject(QStringLiteral("hmac(sha1)"), QCA::SecureArray());
|
||||
|
||||
// create the key
|
||||
QCA::SymmetricKey keyObject(key);
|
||||
// create the key
|
||||
QCA::SymmetricKey keyObject(key);
|
||||
|
||||
// set the HMAC object to use the key
|
||||
hmacObject.setup(key);
|
||||
// that could also have been done in the
|
||||
// QCA::MessageAuthenticationCode constructor
|
||||
// set the HMAC object to use the key
|
||||
hmacObject.setup(key);
|
||||
// that could also have been done in the
|
||||
// QCA::MessageAuthenticationCode constructor
|
||||
|
||||
// we split it into two parts to show incremental update
|
||||
QCA::SecureArray part1(arg.left(3)); // three chars - "hel"
|
||||
QCA::SecureArray part2(arg.mid(3)); // the rest - "lo"
|
||||
hmacObject.update(part1);
|
||||
hmacObject.update(part2);
|
||||
// we split it into two parts to show incremental update
|
||||
QCA::SecureArray part1(arg.left(3)); // three chars - "hel"
|
||||
QCA::SecureArray part2(arg.mid(3)); // the rest - "lo"
|
||||
hmacObject.update(part1);
|
||||
hmacObject.update(part2);
|
||||
|
||||
// no more updates after calling final.
|
||||
QCA::SecureArray resultArray = hmacObject.final();
|
||||
// no more updates after calling final.
|
||||
QCA::SecureArray resultArray = hmacObject.final();
|
||||
|
||||
// convert the result into printable hexadecimal.
|
||||
QString result = QCA::arrayToHex(resultArray.toByteArray());
|
||||
printf("HMAC(SHA1) of \"%s\" with \"%s\" = [%s]\n", arg.data(), key.data(), result.toLatin1().data());
|
||||
}
|
||||
// convert the result into printable hexadecimal.
|
||||
QString result = QCA::arrayToHex(resultArray.toByteArray());
|
||||
printf("HMAC(SHA1) of \"%s\" with \"%s\" = [%s]\n", arg.data(), key.data(), result.toLatin1().data());
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -25,118 +25,97 @@
|
||||
(http://www-128.ibm.com/developerworks/linux/library/l-md5crypt/)
|
||||
*/
|
||||
|
||||
#include <QtCrypto>
|
||||
#include <QCoreApplication>
|
||||
#include <QtCrypto>
|
||||
#include <QtDebug>
|
||||
#include <stdio.h>
|
||||
#include <cstdio>
|
||||
|
||||
#ifdef QT_STATICPLUGIN
|
||||
#include "import_plugins.h"
|
||||
#endif
|
||||
|
||||
QString to64 ( long v , int size )
|
||||
QString to64(long v, int size)
|
||||
{
|
||||
|
||||
// Character set of the encrypted password: A-Za-z0-9./
|
||||
QString itoa64 = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
||||
QString itoa64 = QStringLiteral("./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz");
|
||||
QString result;
|
||||
|
||||
while ( --size >= 0 )
|
||||
{
|
||||
result.append ( itoa64.at ( ( int )( v & 0x3f ) ) );
|
||||
while (--size >= 0) {
|
||||
result.append(itoa64.at((int)(v & 0x3f)));
|
||||
v = v >> 6;
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
|
||||
int byte2unsigned ( int byteValue )
|
||||
int byte2unsigned(int byteValue)
|
||||
{
|
||||
|
||||
int integerToReturn;
|
||||
integerToReturn = (int) byteValue & 0xff;
|
||||
integerToReturn = (int)byteValue & 0xff;
|
||||
return integerToReturn;
|
||||
|
||||
}
|
||||
|
||||
QString qca_md5crypt( const QCA::SecureArray &password, const QCA::SecureArray &salt )
|
||||
QString qca_md5crypt(const QCA::SecureArray &password, const QCA::SecureArray &salt)
|
||||
{
|
||||
QCA::SecureArray finalState, magic_string = "$1$";
|
||||
|
||||
// The md5crypt algorithm uses two separate hashes
|
||||
QCA::Hash hash1( "md5" );
|
||||
QCA::Hash hash2( "md5" );
|
||||
QCA::Hash hash1(QStringLiteral("md5"));
|
||||
QCA::Hash hash2(QStringLiteral("md5"));
|
||||
|
||||
// MD5 Hash #1: pwd, magic string and salt
|
||||
hash1.update ( password );
|
||||
hash1.update ( magic_string );
|
||||
hash1.update ( salt );
|
||||
hash1.update(password);
|
||||
hash1.update(magic_string);
|
||||
hash1.update(salt);
|
||||
|
||||
// MD5 Hash #2: password, salt, password
|
||||
hash2.update ( password );
|
||||
hash2.update ( salt );
|
||||
hash2.update ( password );
|
||||
hash2.update(password);
|
||||
hash2.update(salt);
|
||||
hash2.update(password);
|
||||
|
||||
finalState = hash2.final();
|
||||
|
||||
// Two sets of transformations based on the length of the password
|
||||
for ( int i = password.size() ; i > 0 ; i -= 16 )
|
||||
{
|
||||
for (int i = password.size(); i > 0; i -= 16) {
|
||||
// Update hash1 from offset value (i > 16 ? 16 : i)
|
||||
hash1.update( finalState.toByteArray().left(i > 16 ? 16 : i));
|
||||
hash1.update(finalState.toByteArray().left(i > 16 ? 16 : i));
|
||||
}
|
||||
|
||||
// Clear array bits
|
||||
finalState.fill( 0 );
|
||||
finalState.fill(0);
|
||||
|
||||
for ( int i = password.size() ; i != 0 ; i = i >> 1 )
|
||||
{
|
||||
if ( ( i & 1 ) != 0 )
|
||||
{
|
||||
hash1.update( finalState.toByteArray().left ( 1 ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
hash1.update( password.toByteArray().left ( 1 ) );
|
||||
for (int i = password.size(); i != 0; i = i >> 1) {
|
||||
if ((i & 1) != 0) {
|
||||
hash1.update(finalState.toByteArray().left(1));
|
||||
} else {
|
||||
hash1.update(password.toByteArray().left(1));
|
||||
}
|
||||
}
|
||||
|
||||
finalState = hash1.final();
|
||||
|
||||
// Now build a 1000 entry dictionary...
|
||||
for ( int i = 0 ; i < 1000 ; i++ )
|
||||
{
|
||||
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
hash2.clear();
|
||||
|
||||
if ((i & 1) != 0)
|
||||
{
|
||||
hash2.update ( password );
|
||||
}
|
||||
else
|
||||
{
|
||||
hash2.update ( finalState.toByteArray().left( 16 ));
|
||||
if ((i & 1) != 0) {
|
||||
hash2.update(password);
|
||||
} else {
|
||||
hash2.update(finalState.toByteArray().left(16));
|
||||
}
|
||||
|
||||
if ((i % 3) != 0)
|
||||
{
|
||||
hash2.update ( salt );
|
||||
if ((i % 3) != 0) {
|
||||
hash2.update(salt);
|
||||
}
|
||||
|
||||
if ((i % 7) != 0)
|
||||
{
|
||||
hash2.update ( password );
|
||||
if ((i % 7) != 0) {
|
||||
hash2.update(password);
|
||||
}
|
||||
|
||||
if ((i & 1) != 0)
|
||||
{
|
||||
hash2.update ( finalState.toByteArray().left( 16 ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
hash2.update ( password );
|
||||
if ((i & 1) != 0) {
|
||||
hash2.update(finalState.toByteArray().left(16));
|
||||
} else {
|
||||
hash2.update(password);
|
||||
}
|
||||
|
||||
finalState = hash2.final();
|
||||
@ -146,80 +125,69 @@ QString qca_md5crypt( const QCA::SecureArray &password, const QCA::SecureArray &
|
||||
// Salt is part of the encoded password ($1$<string>$)
|
||||
QString encodedString;
|
||||
|
||||
encodedString.append ( magic_string.toByteArray() );
|
||||
encodedString.append ( salt.toByteArray() );
|
||||
encodedString.append ( "$" );
|
||||
encodedString.append(QString::fromLatin1(magic_string.toByteArray()));
|
||||
encodedString.append(QString::fromLatin1(salt.toByteArray()));
|
||||
encodedString.append(QStringLiteral("$"));
|
||||
|
||||
long l;
|
||||
|
||||
l = ( byte2unsigned (finalState.toByteArray().at(0) ) << 16 |
|
||||
( byte2unsigned (finalState.toByteArray().at(6)) ) << 8 |
|
||||
byte2unsigned (finalState.toByteArray().at(12)) );
|
||||
encodedString.append ( to64 (l, 4) );
|
||||
l = (byte2unsigned(finalState.toByteArray().at(0)) << 16 | (byte2unsigned(finalState.toByteArray().at(6))) << 8 |
|
||||
byte2unsigned(finalState.toByteArray().at(12)));
|
||||
encodedString.append(to64(l, 4));
|
||||
|
||||
l = ( byte2unsigned (finalState.toByteArray().at(1)) << 16 |
|
||||
( byte2unsigned (finalState.toByteArray().at(7))) << 8 |
|
||||
byte2unsigned (finalState.toByteArray().at(13)) );
|
||||
encodedString.append ( to64 (l, 4) );
|
||||
l = (byte2unsigned(finalState.toByteArray().at(1)) << 16 | (byte2unsigned(finalState.toByteArray().at(7))) << 8 |
|
||||
byte2unsigned(finalState.toByteArray().at(13)));
|
||||
encodedString.append(to64(l, 4));
|
||||
|
||||
l = ( byte2unsigned (finalState.toByteArray().at(2)) << 16 |
|
||||
( byte2unsigned (finalState.toByteArray().at(8))) << 8 |
|
||||
byte2unsigned (finalState.toByteArray().at(14)) );
|
||||
encodedString.append ( to64 (l, 4) );
|
||||
l = (byte2unsigned(finalState.toByteArray().at(2)) << 16 | (byte2unsigned(finalState.toByteArray().at(8))) << 8 |
|
||||
byte2unsigned(finalState.toByteArray().at(14)));
|
||||
encodedString.append(to64(l, 4));
|
||||
|
||||
l = ( byte2unsigned (finalState.toByteArray().at(3)) << 16 |
|
||||
( byte2unsigned (finalState.toByteArray().at(9))) << 8 |
|
||||
byte2unsigned (finalState.toByteArray().at(15)) );
|
||||
encodedString.append ( to64 (l, 4) );
|
||||
l = (byte2unsigned(finalState.toByteArray().at(3)) << 16 | (byte2unsigned(finalState.toByteArray().at(9))) << 8 |
|
||||
byte2unsigned(finalState.toByteArray().at(15)));
|
||||
encodedString.append(to64(l, 4));
|
||||
|
||||
l = ( byte2unsigned (finalState.toByteArray().at(4)) << 16 |
|
||||
( byte2unsigned (finalState.toByteArray().at(10))) << 8 |
|
||||
byte2unsigned (finalState.toByteArray().at(5)) );
|
||||
encodedString.append ( to64 (l, 4) );
|
||||
l = (byte2unsigned(finalState.toByteArray().at(4)) << 16 | (byte2unsigned(finalState.toByteArray().at(10))) << 8 |
|
||||
byte2unsigned(finalState.toByteArray().at(5)));
|
||||
encodedString.append(to64(l, 4));
|
||||
|
||||
l = byte2unsigned (finalState.toByteArray().at(11));
|
||||
encodedString.append ( to64 (l, 2) );
|
||||
l = byte2unsigned(finalState.toByteArray().at(11));
|
||||
encodedString.append(to64(l, 2));
|
||||
|
||||
return encodedString;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
|
||||
// the Initializer object sets things up, and
|
||||
// also does cleanup when it goes out of scope
|
||||
QCA::Initializer init;
|
||||
|
||||
QCoreApplication app ( argc, argv );
|
||||
QCoreApplication app(argc, argv);
|
||||
|
||||
QCA::SecureArray password, salt;
|
||||
|
||||
if ( argc < 3 )
|
||||
{
|
||||
printf ( "Usage: %s password salt (salt without $1$)\n" , argv[0] );
|
||||
if (argc < 3) {
|
||||
printf("Usage: %s password salt (salt without $1$)\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
password.append( argv[1] );
|
||||
password.append(argv[1]);
|
||||
|
||||
salt.append( argv[2] );
|
||||
salt.append(argv[2]);
|
||||
|
||||
// must always check that an algorithm is supported before using it
|
||||
if( !QCA::isSupported( "md5" ) )
|
||||
printf ("MD5 hash not supported!\n");
|
||||
else
|
||||
{
|
||||
QString result = qca_md5crypt( password, salt );
|
||||
if (!QCA::isSupported("md5"))
|
||||
printf("MD5 hash not supported!\n");
|
||||
else {
|
||||
QString result = qca_md5crypt(password, salt);
|
||||
|
||||
printf ("md5crypt [ %s , %s ] = '%s'\n" , password.data(), salt.data() , qPrintable(result) );
|
||||
printf("md5crypt [ %s , %s ] = '%s'\n", password.data(), salt.data(), qPrintable(result));
|
||||
|
||||
// this is equivalent if you have GNU libc 2.0
|
||||
// printf( "GNU md5crypt [ %s , %s ] = '%s'\n", password.data(), salt.data(), crypt( password.data(), ( "$1$"+salt ).data() ) );
|
||||
// printf( "GNU md5crypt [ %s , %s ] = '%s'\n", password.data(), salt.data(), crypt( password.data(), (
|
||||
// "$1$"+salt ).data() ) );
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -20,8 +20,8 @@
|
||||
*/
|
||||
|
||||
// QtCrypto has the declarations for all of QCA
|
||||
#include <QtCrypto>
|
||||
#include <QCoreApplication>
|
||||
#include <QtCrypto>
|
||||
|
||||
#include <iostream>
|
||||
#include <qstringlist.h>
|
||||
@ -44,15 +44,15 @@ int main(int argc, char **argv)
|
||||
QCA::scanForPlugins();
|
||||
|
||||
// this gives us all the plugin providers as a list
|
||||
QCA::ProviderList qcaProviders = QCA::providers();
|
||||
for (int i = 0; i < qcaProviders.size(); ++i) {
|
||||
// each provider has a name, which we can display
|
||||
std::cout << qcaProviders[i]->name().toLatin1().data() << ": ";
|
||||
// ... and also a list of features
|
||||
QStringList capabilities = qcaProviders[i]->features();
|
||||
// we turn the string list back into a single string,
|
||||
// and display it as well
|
||||
std::cout << capabilities.join(", ").toLatin1().data() << std::endl;
|
||||
const QCA::ProviderList qcaProviders = QCA::providers();
|
||||
for (const QCA::Provider *provider : qcaProviders) {
|
||||
// each provider has a name, which we can display
|
||||
std::cout << provider->name().toLatin1().data() << ": ";
|
||||
// ... and also a list of features
|
||||
QStringList capabilities = provider->features();
|
||||
// we turn the string list back into a single string,
|
||||
// and display it as well
|
||||
std::cout << capabilities.join(QStringLiteral(", ")).toLatin1().data() << std::endl;
|
||||
}
|
||||
|
||||
// Note that the default provider isn't included in
|
||||
@ -61,7 +61,6 @@ int main(int argc, char **argv)
|
||||
// However it is still possible to get the features
|
||||
// supported by the default provider
|
||||
QStringList capabilities = QCA::defaultFeatures();
|
||||
std::cout << capabilities.join(", ").toLatin1().data() << std::endl;
|
||||
std::cout << capabilities.join(QStringLiteral(", ")).toLatin1().data() << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -20,7 +20,6 @@
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
#include <QtCrypto>
|
||||
|
||||
#include <QCoreApplication>
|
||||
@ -31,7 +30,7 @@
|
||||
#include "import_plugins.h"
|
||||
#endif
|
||||
|
||||
int main(int argc, char** argv)
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
// the Initializer object sets things up, and
|
||||
// also does cleanup when it goes out of scope
|
||||
@ -40,37 +39,37 @@ int main(int argc, char** argv)
|
||||
QCoreApplication app(argc, argv);
|
||||
|
||||
// We need to ensure that we have certificate handling support
|
||||
if ( !QCA::isSupported( "cert" ) ) {
|
||||
std::cout << "Sorry, no PKI certificate support" << std::endl;
|
||||
return 1;
|
||||
if (!QCA::isSupported("cert")) {
|
||||
std::cout << "Sorry, no PKI certificate support" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Read in a private key
|
||||
QCA::PrivateKey privKey;
|
||||
QCA::PrivateKey privKey;
|
||||
QCA::ConvertResult convRes;
|
||||
QCA::SecureArray passPhrase = "start";
|
||||
privKey = QCA::PrivateKey::fromPEMFile( "Userkey.pem", passPhrase, &convRes );
|
||||
if ( convRes != QCA::ConvertGood ) {
|
||||
std::cout << "Sorry, could not import Private Key" << std::endl;
|
||||
return 1;
|
||||
QCA::SecureArray passPhrase = "start";
|
||||
privKey = QCA::PrivateKey::fromPEMFile(QStringLiteral("Userkey.pem"), passPhrase, &convRes);
|
||||
if (convRes != QCA::ConvertGood) {
|
||||
std::cout << "Sorry, could not import Private Key" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Read in a matching public key cert
|
||||
// you could also build this using the fromPEMFile() method
|
||||
QCA::Certificate pubCert( "User.pem" );
|
||||
if ( pubCert.isNull() ) {
|
||||
std::cout << "Sorry, could not import public key certificate" << std::endl;
|
||||
return 1;
|
||||
QCA::Certificate pubCert(QStringLiteral("User.pem"));
|
||||
if (pubCert.isNull()) {
|
||||
std::cout << "Sorry, could not import public key certificate" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
// We are building the certificate into a SecureMessageKey object, via a
|
||||
// CertificateChain
|
||||
QCA::SecureMessageKey secMsgKey;
|
||||
QCA::CertificateChain chain;
|
||||
chain += pubCert;
|
||||
secMsgKey.setX509CertificateChain( chain );
|
||||
secMsgKey.setX509CertificateChain(chain);
|
||||
|
||||
// build up a SecureMessage object, based on our public key certificate
|
||||
QCA::CMS cms;
|
||||
QCA::CMS cms;
|
||||
QCA::SecureMessage msg(&cms);
|
||||
msg.setRecipient(secMsgKey);
|
||||
|
||||
@ -85,33 +84,31 @@ int main(int argc, char** argv)
|
||||
msg.waitForFinished(1000);
|
||||
|
||||
// check to see if it worked
|
||||
if(!msg.success())
|
||||
{
|
||||
std::cout << "Error encrypting: " << msg.errorCode() << std::endl;
|
||||
return 1;
|
||||
if (!msg.success()) {
|
||||
std::cout << "Error encrypting: " << msg.errorCode() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// get the result
|
||||
QCA::SecureArray cipherText = msg.read();
|
||||
QCA::Base64 enc;
|
||||
QCA::Base64 enc;
|
||||
std::cout << plainText.data() << " encrypts to (in base 64): ";
|
||||
std::cout << qPrintable( enc.arrayToString( cipherText ) ) << std::endl;
|
||||
std::cout << qPrintable(enc.arrayToString(cipherText)) << std::endl;
|
||||
|
||||
// Show we can decrypt it with the private key
|
||||
if ( !privKey.canDecrypt() ) {
|
||||
std::cout << "Private key cannot be used to decrypt" << std::endl;
|
||||
return 1;
|
||||
if (!privKey.canDecrypt()) {
|
||||
std::cout << "Private key cannot be used to decrypt" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
QCA::SecureArray plainTextResult;
|
||||
if ( 0 == privKey.decrypt(cipherText, &plainTextResult, QCA::EME_PKCS1_OAEP ) ) {
|
||||
std::cout << "Decryption process failed" << std::endl;
|
||||
return 1;
|
||||
if (0 == privKey.decrypt(cipherText, &plainTextResult, QCA::EME_PKCS1_OAEP)) {
|
||||
std::cout << "Decryption process failed" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::cout << qPrintable( enc.arrayToString( cipherText ) );
|
||||
std::cout << qPrintable(enc.arrayToString(cipherText));
|
||||
std::cout << " (in base 64) decrypts to: ";
|
||||
std::cout << plainTextResult.data() << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -33,41 +33,40 @@
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
// the Initializer object sets things up, and
|
||||
// also does cleanup when it goes out of scope
|
||||
QCA::Initializer init;
|
||||
// the Initializer object sets things up, and
|
||||
// also does cleanup when it goes out of scope
|
||||
QCA::Initializer init;
|
||||
|
||||
QCoreApplication app(argc, argv);
|
||||
QCoreApplication app(argc, argv);
|
||||
|
||||
qDebug() << "This example generates random numbers";
|
||||
qDebug() << "This example generates random numbers";
|
||||
|
||||
int randInt;
|
||||
// This is the standard way to generate a random integer.
|
||||
randInt = QCA::Random::randomInt();
|
||||
qDebug() << "A random number: " << randInt;
|
||||
int randInt;
|
||||
// This is the standard way to generate a random integer.
|
||||
randInt = QCA::Random::randomInt();
|
||||
qDebug() << "A random number: " << randInt;
|
||||
|
||||
// If you wanted a random character (octet), you could
|
||||
// use something like:
|
||||
unsigned char randChar;
|
||||
randChar = QCA::Random::randomChar();
|
||||
// It might not be printable, so this may not produce output
|
||||
std::cout << "A random character: " << randChar << std::endl;
|
||||
// If you wanted a random character (octet), you could
|
||||
// use something like:
|
||||
unsigned char randChar;
|
||||
randChar = QCA::Random::randomChar();
|
||||
// It might not be printable, so this may not produce output
|
||||
std::cout << "A random character: " << randChar << std::endl;
|
||||
|
||||
QCA::SecureArray tenBytes(10);
|
||||
// If you need more random values, you may want to
|
||||
// get an array, as shown below.
|
||||
tenBytes = QCA::Random::randomArray(10);
|
||||
QCA::SecureArray tenBytes(10);
|
||||
// If you need more random values, you may want to
|
||||
// get an array, as shown below.
|
||||
tenBytes = QCA::Random::randomArray(10);
|
||||
|
||||
// To make this viewable, we convert to hexadecimal.
|
||||
std::cout << "A random 10 byte array (in hex): ";
|
||||
std::cout << qPrintable(QCA::Hex().arrayToString(tenBytes)) << std::endl;
|
||||
// To make this viewable, we convert to hexadecimal.
|
||||
std::cout << "A random 10 byte array (in hex): ";
|
||||
std::cout << qPrintable(QCA::Hex().arrayToString(tenBytes)) << std::endl;
|
||||
|
||||
// Under some circumstances, you may want to create a
|
||||
// Random object, rather than a static public member function.
|
||||
// This isn't normally the easiest way, but it does work
|
||||
QCA::Random myRandomObject;
|
||||
randChar = myRandomObject.nextByte();
|
||||
tenBytes = myRandomObject.nextBytes(10);
|
||||
return 0;
|
||||
// Under some circumstances, you may want to create a
|
||||
// Random object, rather than a static public member function.
|
||||
// This isn't normally the easiest way, but it does work
|
||||
QCA::Random myRandomObject;
|
||||
randChar = myRandomObject.nextByte();
|
||||
tenBytes = myRandomObject.nextBytes(10);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -20,8 +20,8 @@
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <QtCrypto>
|
||||
#include <QCoreApplication>
|
||||
#include <QtCrypto>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
@ -43,115 +43,109 @@ int main(int argc, char **argv)
|
||||
|
||||
// We demonstrate PEM usage here, so we need to test for
|
||||
// supportedIOTypes, not just supportedTypes
|
||||
if(!QCA::isSupported("pkey") ||
|
||||
!QCA::PKey::supportedIOTypes().contains(QCA::PKey::RSA))
|
||||
std::cout << "RSA not supported!\n";
|
||||
if (!QCA::isSupported("pkey") || !QCA::PKey::supportedIOTypes().contains(QCA::PKey::RSA))
|
||||
std::cout << "RSA not supported!\n";
|
||||
else {
|
||||
// When creating a public / private key pair, you make the
|
||||
// private key, and then extract the public key component from it
|
||||
// Using RSA is very common, however DSA can provide equivalent
|
||||
// signature/verification. This example applies to DSA to the
|
||||
// extent that the operations work on that key type.
|
||||
// When creating a public / private key pair, you make the
|
||||
// private key, and then extract the public key component from it
|
||||
// Using RSA is very common, however DSA can provide equivalent
|
||||
// signature/verification. This example applies to DSA to the
|
||||
// extent that the operations work on that key type.
|
||||
|
||||
// QCA provides KeyGenerator as a convenient source of new keys,
|
||||
// however you could also import an existing key instead.
|
||||
QCA::PrivateKey seckey = QCA::KeyGenerator().createRSA(1024);
|
||||
if(seckey.isNull()) {
|
||||
std::cout << "Failed to make private RSA key" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
// QCA provides KeyGenerator as a convenient source of new keys,
|
||||
// however you could also import an existing key instead.
|
||||
QCA::PrivateKey seckey = QCA::KeyGenerator().createRSA(1024);
|
||||
if (seckey.isNull()) {
|
||||
std::cout << "Failed to make private RSA key" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
QCA::PublicKey pubkey = seckey.toPublicKey();
|
||||
QCA::PublicKey pubkey = seckey.toPublicKey();
|
||||
|
||||
// check if the key can encrypt
|
||||
if(!pubkey.canEncrypt()) {
|
||||
std::cout << "Error: this kind of key cannot encrypt" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
// check if the key can encrypt
|
||||
if (!pubkey.canEncrypt()) {
|
||||
std::cout << "Error: this kind of key cannot encrypt" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// encrypt some data - note that only the public key is required
|
||||
// you must also choose the algorithm to be used
|
||||
QCA::SecureArray result = pubkey.encrypt(arg, QCA::EME_PKCS1_OAEP);
|
||||
if(result.isEmpty()) {
|
||||
std::cout << "Error encrypting" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
// encrypt some data - note that only the public key is required
|
||||
// you must also choose the algorithm to be used
|
||||
QCA::SecureArray result = pubkey.encrypt(arg, QCA::EME_PKCS1_OAEP);
|
||||
if (result.isEmpty()) {
|
||||
std::cout << "Error encrypting" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// output the encrypted data
|
||||
QString rstr = QCA::arrayToHex(result.toByteArray());
|
||||
std::cout << "\"" << arg.data() << "\" encrypted with RSA is \"";
|
||||
std::cout << qPrintable(rstr) << "\"" << std::endl;
|
||||
// output the encrypted data
|
||||
QString rstr = QCA::arrayToHex(result.toByteArray());
|
||||
std::cout << "\"" << arg.data() << "\" encrypted with RSA is \"";
|
||||
std::cout << qPrintable(rstr) << "\"" << std::endl;
|
||||
|
||||
// save the private key - in a real example, make sure this goes
|
||||
// somewhere secure and has a good pass phrase
|
||||
// You can use the same technique with the public key too.
|
||||
QCA::SecureArray passPhrase = "pass phrase";
|
||||
seckey.toPEMFile("keyprivate.pem", passPhrase);
|
||||
// save the private key - in a real example, make sure this goes
|
||||
// somewhere secure and has a good pass phrase
|
||||
// You can use the same technique with the public key too.
|
||||
QCA::SecureArray passPhrase = "pass phrase";
|
||||
seckey.toPEMFile(QStringLiteral("keyprivate.pem"), passPhrase);
|
||||
|
||||
// Read that key back in, checking if the read succeeded
|
||||
QCA::ConvertResult conversionResult;
|
||||
QCA::PrivateKey privateKey = QCA::PrivateKey::fromPEMFile( "keyprivate.pem",
|
||||
passPhrase,
|
||||
&conversionResult);
|
||||
if (! (QCA::ConvertGood == conversionResult) ) {
|
||||
std::cout << "Private key read failed" << std::endl;
|
||||
}
|
||||
// Read that key back in, checking if the read succeeded
|
||||
QCA::ConvertResult conversionResult;
|
||||
QCA::PrivateKey privateKey =
|
||||
QCA::PrivateKey::fromPEMFile(QStringLiteral("keyprivate.pem"), passPhrase, &conversionResult);
|
||||
if (!(QCA::ConvertGood == conversionResult)) {
|
||||
std::cout << "Private key read failed" << std::endl;
|
||||
}
|
||||
|
||||
// now decrypt that encrypted data using the private key that
|
||||
// we read in. The algorithm is the same.
|
||||
QCA::SecureArray decrypt;
|
||||
if(0 == privateKey.decrypt(result, &decrypt, QCA::EME_PKCS1_OAEP)) {
|
||||
std::cout << "Error decrypting.\n";
|
||||
return 1;
|
||||
}
|
||||
// now decrypt that encrypted data using the private key that
|
||||
// we read in. The algorithm is the same.
|
||||
QCA::SecureArray decrypt;
|
||||
if (0 == privateKey.decrypt(result, &decrypt, QCA::EME_PKCS1_OAEP)) {
|
||||
std::cout << "Error decrypting.\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
// output the resulting decrypted string
|
||||
std::cout << "\"" << qPrintable(rstr) << "\" decrypted with RSA is \"";
|
||||
std::cout << decrypt.data() << "\"" << std::endl;
|
||||
// output the resulting decrypted string
|
||||
std::cout << "\"" << qPrintable(rstr) << "\" decrypted with RSA is \"";
|
||||
std::cout << decrypt.data() << "\"" << std::endl;
|
||||
|
||||
// Some private keys can also be used for producing signatures
|
||||
if (!privateKey.canSign()) {
|
||||
std::cout << "Error: this kind of key cannot sign" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
privateKey.startSign(QCA::EMSA3_MD5);
|
||||
privateKey.update(arg); // just reuse the same message
|
||||
QByteArray argSig = privateKey.signature();
|
||||
|
||||
// Some private keys can also be used for producing signatures
|
||||
if(!privateKey.canSign()) {
|
||||
std::cout << "Error: this kind of key cannot sign" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
privateKey.startSign( QCA::EMSA3_MD5 );
|
||||
privateKey.update( arg ); // just reuse the same message
|
||||
QByteArray argSig = privateKey.signature();
|
||||
// instead of using the startSign(), update(), signature() calls,
|
||||
// you may be better doing the whole thing in one go, using the
|
||||
// signMessage call. Of course you need the whole message in one
|
||||
// hit, which may or may not be a problem
|
||||
|
||||
// instead of using the startSign(), update(), signature() calls,
|
||||
// you may be better doing the whole thing in one go, using the
|
||||
// signMessage call. Of course you need the whole message in one
|
||||
// hit, which may or may not be a problem
|
||||
// output the resulting signature
|
||||
rstr = QCA::arrayToHex(argSig);
|
||||
std::cout << "Signature for \"" << arg.data() << "\" using RSA, is ";
|
||||
std::cout << "\"" << qPrintable(rstr) << "\"" << std::endl;
|
||||
|
||||
// output the resulting signature
|
||||
rstr = QCA::arrayToHex(argSig);
|
||||
std::cout << "Signature for \"" << arg.data() << "\" using RSA, is ";
|
||||
std::cout << "\"" << qPrintable( rstr ) << "\"" << std::endl;
|
||||
|
||||
// to check a signature, we must check that the key is
|
||||
// appropriate
|
||||
if(pubkey.canVerify()) {
|
||||
pubkey.startVerify( QCA::EMSA3_MD5 );
|
||||
pubkey.update( arg );
|
||||
if ( pubkey.validSignature( argSig ) ) {
|
||||
std::cout << "Signature is valid" << std::endl;
|
||||
} else {
|
||||
std::cout << "Bad signature" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
// We can also do the verification in a single step if we
|
||||
// have all the message
|
||||
if ( pubkey.canVerify() &&
|
||||
pubkey.verifyMessage( arg, argSig, QCA::EMSA3_MD5 ) ) {
|
||||
std::cout << "Signature is valid" << std::endl;
|
||||
} else {
|
||||
std::cout << "Signature could not be verified" << std::endl;
|
||||
}
|
||||
// to check a signature, we must check that the key is
|
||||
// appropriate
|
||||
if (pubkey.canVerify()) {
|
||||
pubkey.startVerify(QCA::EMSA3_MD5);
|
||||
pubkey.update(arg);
|
||||
if (pubkey.validSignature(argSig)) {
|
||||
std::cout << "Signature is valid" << std::endl;
|
||||
} else {
|
||||
std::cout << "Bad signature" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
// We can also do the verification in a single step if we
|
||||
// have all the message
|
||||
if (pubkey.canVerify() && pubkey.verifyMessage(arg, argSig, QCA::EMSA3_MD5)) {
|
||||
std::cout << "Signature is valid" << std::endl;
|
||||
} else {
|
||||
std::cout << "Signature could not be verified" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,10 @@
|
||||
set(saslclient_bin_SRCS saslclient.cpp)
|
||||
|
||||
MY_AUTOMOC( saslclient_bin_SRCS)
|
||||
|
||||
add_executable(saslclient ${saslclient_bin_SRCS})
|
||||
|
||||
target_link_qca_libraries(saslclient)
|
||||
target_link_libraries(saslclient ${QT_QTNETWORK_LIBRARY})
|
||||
if(QT6)
|
||||
target_link_libraries(saslclient Qt6::Network)
|
||||
else()
|
||||
target_link_libraries(saslclient Qt5::Network)
|
||||
endif()
|
||||
|
@ -21,10 +21,10 @@
|
||||
*/
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QTimer>
|
||||
#include <QTcpSocket>
|
||||
#include <QTcpServer>
|
||||
#include <stdio.h>
|
||||
#include <QTcpSocket>
|
||||
#include <QTimer>
|
||||
#include <cstdio>
|
||||
|
||||
// QtCrypto has the declarations for all of QCA
|
||||
#include <QtCrypto>
|
||||
@ -35,535 +35,527 @@
|
||||
|
||||
static QString prompt(const QString &s)
|
||||
{
|
||||
printf("* %s ", qPrintable(s));
|
||||
fflush(stdout);
|
||||
char line[256];
|
||||
fgets(line, 255, stdin);
|
||||
QString result = line;
|
||||
if(result[result.length()-1] == '\n')
|
||||
result.truncate(result.length()-1);
|
||||
return result;
|
||||
printf("* %s ", qPrintable(s));
|
||||
fflush(stdout);
|
||||
char line[256];
|
||||
fgets(line, 255, stdin);
|
||||
QString result = QString::fromLatin1(line);
|
||||
if (result[result.length() - 1] == QLatin1Char('\n'))
|
||||
result.truncate(result.length() - 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
static QString socketErrorToString(QAbstractSocket::SocketError x)
|
||||
{
|
||||
QString s;
|
||||
switch(x)
|
||||
{
|
||||
case QAbstractSocket::ConnectionRefusedError:
|
||||
s = "connection refused or timed out"; break;
|
||||
case QAbstractSocket::RemoteHostClosedError:
|
||||
s = "remote host closed the connection"; break;
|
||||
case QAbstractSocket::HostNotFoundError:
|
||||
s = "host not found"; break;
|
||||
case QAbstractSocket::SocketAccessError:
|
||||
s = "access error"; break;
|
||||
case QAbstractSocket::SocketResourceError:
|
||||
s = "too many sockets"; break;
|
||||
case QAbstractSocket::SocketTimeoutError:
|
||||
s = "operation timed out"; break;
|
||||
case QAbstractSocket::DatagramTooLargeError:
|
||||
s = "datagram was larger than system limit"; break;
|
||||
case QAbstractSocket::NetworkError:
|
||||
s = "network error"; break;
|
||||
case QAbstractSocket::AddressInUseError:
|
||||
s = "address is already in use"; break;
|
||||
case QAbstractSocket::SocketAddressNotAvailableError:
|
||||
s = "address does not belong to the host"; break;
|
||||
case QAbstractSocket::UnsupportedSocketOperationError:
|
||||
s = "operation is not supported by the local operating system"; break;
|
||||
default:
|
||||
s = "unknown socket error"; break;
|
||||
}
|
||||
return s;
|
||||
QString s;
|
||||
switch (x) {
|
||||
case QAbstractSocket::ConnectionRefusedError:
|
||||
s = QStringLiteral("connection refused or timed out");
|
||||
break;
|
||||
case QAbstractSocket::RemoteHostClosedError:
|
||||
s = QStringLiteral("remote host closed the connection");
|
||||
break;
|
||||
case QAbstractSocket::HostNotFoundError:
|
||||
s = QStringLiteral("host not found");
|
||||
break;
|
||||
case QAbstractSocket::SocketAccessError:
|
||||
s = QStringLiteral("access error");
|
||||
break;
|
||||
case QAbstractSocket::SocketResourceError:
|
||||
s = QStringLiteral("too many sockets");
|
||||
break;
|
||||
case QAbstractSocket::SocketTimeoutError:
|
||||
s = QStringLiteral("operation timed out");
|
||||
break;
|
||||
case QAbstractSocket::DatagramTooLargeError:
|
||||
s = QStringLiteral("datagram was larger than system limit");
|
||||
break;
|
||||
case QAbstractSocket::NetworkError:
|
||||
s = QStringLiteral("network error");
|
||||
break;
|
||||
case QAbstractSocket::AddressInUseError:
|
||||
s = QStringLiteral("address is already in use");
|
||||
break;
|
||||
case QAbstractSocket::SocketAddressNotAvailableError:
|
||||
s = QStringLiteral("address does not belong to the host");
|
||||
break;
|
||||
case QAbstractSocket::UnsupportedSocketOperationError:
|
||||
s = QStringLiteral("operation is not supported by the local operating system");
|
||||
break;
|
||||
default:
|
||||
s = QStringLiteral("unknown socket error");
|
||||
break;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
static QString saslAuthConditionToString(QCA::SASL::AuthCondition x)
|
||||
{
|
||||
QString s;
|
||||
switch(x)
|
||||
{
|
||||
case QCA::SASL::NoMechanism:
|
||||
s = "no appropriate mechanism could be negotiated"; break;
|
||||
case QCA::SASL::BadProtocol:
|
||||
s = "bad SASL protocol"; break;
|
||||
case QCA::SASL::BadServer:
|
||||
s = "server failed mutual authentication"; break;
|
||||
// AuthFail or unknown (including those defined for server only)
|
||||
default:
|
||||
s = "generic authentication failure"; break;
|
||||
};
|
||||
return s;
|
||||
QString s;
|
||||
switch (x) {
|
||||
case QCA::SASL::NoMechanism:
|
||||
s = QStringLiteral("no appropriate mechanism could be negotiated");
|
||||
break;
|
||||
case QCA::SASL::BadProtocol:
|
||||
s = QStringLiteral("bad SASL protocol");
|
||||
break;
|
||||
case QCA::SASL::BadServer:
|
||||
s = QStringLiteral("server failed mutual authentication");
|
||||
break;
|
||||
// AuthFail or unknown (including those defined for server only)
|
||||
default:
|
||||
s = QStringLiteral("generic authentication failure");
|
||||
break;
|
||||
};
|
||||
return s;
|
||||
}
|
||||
|
||||
class ClientTest : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
QString host, proto, authzid, realm, user, pass;
|
||||
int port;
|
||||
bool no_authzid, no_realm;
|
||||
int mode; // 0 = receive mechanism list, 1 = sasl negotiation, 2 = app
|
||||
QTcpSocket *sock;
|
||||
QCA::SASL *sasl;
|
||||
QByteArray inbuf;
|
||||
bool sock_done;
|
||||
int waitCycles;
|
||||
QString host, proto, authzid, realm, user, pass;
|
||||
int port;
|
||||
bool no_authzid, no_realm;
|
||||
int mode; // 0 = receive mechanism list, 1 = sasl negotiation, 2 = app
|
||||
QTcpSocket *sock;
|
||||
QCA::SASL * sasl;
|
||||
QByteArray inbuf;
|
||||
bool sock_done;
|
||||
int waitCycles;
|
||||
|
||||
public:
|
||||
ClientTest(const QString &_host, int _port, const QString &_proto, const QString &_authzid, const QString &_realm, const QString &_user, const QString &_pass, bool _no_authzid, bool _no_realm) :
|
||||
host(_host),
|
||||
proto(_proto),
|
||||
authzid(_authzid),
|
||||
realm(_realm),
|
||||
user(_user),
|
||||
pass(_pass),
|
||||
port(_port),
|
||||
no_authzid(_no_authzid),
|
||||
no_realm(_no_realm),
|
||||
sock_done(false),
|
||||
waitCycles(0)
|
||||
{
|
||||
sock = new QTcpSocket(this);
|
||||
connect(sock, SIGNAL(connected()), SLOT(sock_connected()));
|
||||
connect(sock, SIGNAL(readyRead()), SLOT(sock_readyRead()));
|
||||
connect(sock, SIGNAL(error(QAbstractSocket::SocketError)), SLOT(sock_error(QAbstractSocket::SocketError)));
|
||||
ClientTest(const QString &_host,
|
||||
int _port,
|
||||
const QString &_proto,
|
||||
const QString &_authzid,
|
||||
const QString &_realm,
|
||||
const QString &_user,
|
||||
const QString &_pass,
|
||||
bool _no_authzid,
|
||||
bool _no_realm)
|
||||
: host(_host)
|
||||
, proto(_proto)
|
||||
, authzid(_authzid)
|
||||
, realm(_realm)
|
||||
, user(_user)
|
||||
, pass(_pass)
|
||||
, port(_port)
|
||||
, no_authzid(_no_authzid)
|
||||
, no_realm(_no_realm)
|
||||
, sock_done(false)
|
||||
, waitCycles(0)
|
||||
{
|
||||
sock = new QTcpSocket(this);
|
||||
connect(sock, &QTcpSocket::connected, this, &ClientTest::sock_connected);
|
||||
connect(sock, &QTcpSocket::readyRead, this, &ClientTest::sock_readyRead);
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
|
||||
connect(sock, &QTcpSocket::errorOccurred, this, &ClientTest::sock_error);
|
||||
#else
|
||||
connect(sock, QOverload<QAbstractSocket::SocketError>::of(&QTcpSocket::error), this, &ClientTest::sock_error);
|
||||
#endif
|
||||
|
||||
sasl = new QCA::SASL(this);
|
||||
connect(sasl, SIGNAL(clientStarted(bool, const QByteArray &)), SLOT(sasl_clientFirstStep(bool, const QByteArray &)));
|
||||
connect(sasl, SIGNAL(nextStep(const QByteArray &)), SLOT(sasl_nextStep(const QByteArray &)));
|
||||
connect(sasl, SIGNAL(needParams(const QCA::SASL::Params &)), SLOT(sasl_needParams(const QCA::SASL::Params &)));
|
||||
connect(sasl, SIGNAL(authenticated()), SLOT(sasl_authenticated()));
|
||||
connect(sasl, SIGNAL(readyRead()), SLOT(sasl_readyRead()));
|
||||
connect(sasl, SIGNAL(readyReadOutgoing()), SLOT(sasl_readyReadOutgoing()));
|
||||
connect(sasl, SIGNAL(error()), SLOT(sasl_error()));
|
||||
}
|
||||
sasl = new QCA::SASL(this);
|
||||
connect(sasl, &QCA::SASL::clientStarted, this, &ClientTest::sasl_clientFirstStep);
|
||||
connect(sasl, &QCA::SASL::nextStep, this, &ClientTest::sasl_nextStep);
|
||||
connect(sasl, &QCA::SASL::needParams, this, &ClientTest::sasl_needParams);
|
||||
connect(sasl, &QCA::SASL::authenticated, this, &ClientTest::sasl_authenticated);
|
||||
connect(sasl, &QCA::SASL::readyRead, this, &ClientTest::sasl_readyRead);
|
||||
connect(sasl, &QCA::SASL::readyReadOutgoing, this, &ClientTest::sasl_readyReadOutgoing);
|
||||
connect(sasl, &QCA::SASL::error, this, &ClientTest::sasl_error);
|
||||
}
|
||||
|
||||
public slots:
|
||||
void start()
|
||||
{
|
||||
mode = 0; // mech list mode
|
||||
public Q_SLOTS:
|
||||
void start()
|
||||
{
|
||||
mode = 0; // mech list mode
|
||||
|
||||
int flags = 0;
|
||||
flags |= QCA::SASL::AllowPlain;
|
||||
flags |= QCA::SASL::AllowAnonymous;
|
||||
sasl->setConstraints((QCA::SASL::AuthFlags)flags, 0, 256);
|
||||
int flags = 0;
|
||||
flags |= QCA::SASL::AllowPlain;
|
||||
flags |= QCA::SASL::AllowAnonymous;
|
||||
sasl->setConstraints((QCA::SASL::AuthFlags)flags, 0, 256);
|
||||
|
||||
if(!user.isEmpty())
|
||||
sasl->setUsername(user);
|
||||
if(!authzid.isEmpty())
|
||||
sasl->setAuthzid(authzid);
|
||||
if(!pass.isEmpty())
|
||||
sasl->setPassword(pass.toUtf8());
|
||||
if(!realm.isEmpty())
|
||||
sasl->setRealm(realm);
|
||||
if (!user.isEmpty())
|
||||
sasl->setUsername(user);
|
||||
if (!authzid.isEmpty())
|
||||
sasl->setAuthzid(authzid);
|
||||
if (!pass.isEmpty())
|
||||
sasl->setPassword(pass.toUtf8());
|
||||
if (!realm.isEmpty())
|
||||
sasl->setRealm(realm);
|
||||
|
||||
printf("Connecting to %s:%d, for protocol %s\n", qPrintable(host), port, qPrintable(proto));
|
||||
sock->connectToHost(host, port);
|
||||
}
|
||||
printf("Connecting to %s:%d, for protocol %s\n", qPrintable(host), port, qPrintable(proto));
|
||||
sock->connectToHost(host, port);
|
||||
}
|
||||
|
||||
signals:
|
||||
void quit();
|
||||
Q_SIGNALS:
|
||||
void quit();
|
||||
|
||||
private slots:
|
||||
void sock_connected()
|
||||
{
|
||||
printf("Connected to server. Awaiting mechanism list...\n");
|
||||
}
|
||||
private Q_SLOTS:
|
||||
void sock_connected()
|
||||
{
|
||||
printf("Connected to server. Awaiting mechanism list...\n");
|
||||
}
|
||||
|
||||
void sock_error(QAbstractSocket::SocketError x)
|
||||
{
|
||||
if(x == QAbstractSocket::RemoteHostClosedError)
|
||||
{
|
||||
if(mode == 2) // app mode, where disconnect means completion
|
||||
{
|
||||
sock_done = true;
|
||||
tryFinished();
|
||||
return;
|
||||
}
|
||||
else // any other mode, where disconnect is an error
|
||||
{
|
||||
printf("Error: server closed connection unexpectedly.\n");
|
||||
emit quit();
|
||||
return;
|
||||
}
|
||||
}
|
||||
void sock_error(QAbstractSocket::SocketError x)
|
||||
{
|
||||
if (x == QAbstractSocket::RemoteHostClosedError) {
|
||||
if (mode == 2) // app mode, where disconnect means completion
|
||||
{
|
||||
sock_done = true;
|
||||
tryFinished();
|
||||
return;
|
||||
} else // any other mode, where disconnect is an error
|
||||
{
|
||||
printf("Error: server closed connection unexpectedly.\n");
|
||||
emit quit();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
printf("Error: socket: %s\n", qPrintable(socketErrorToString(x)));
|
||||
emit quit();
|
||||
}
|
||||
printf("Error: socket: %s\n", qPrintable(socketErrorToString(x)));
|
||||
emit quit();
|
||||
}
|
||||
|
||||
void sock_readyRead()
|
||||
{
|
||||
if(mode == 2) // app mode
|
||||
{
|
||||
QByteArray a = sock->readAll();
|
||||
printf("Read %d bytes\n", a.size());
|
||||
void sock_readyRead()
|
||||
{
|
||||
if (mode == 2) // app mode
|
||||
{
|
||||
QByteArray a = sock->readAll();
|
||||
printf("Read %d bytes\n", int(a.size()));
|
||||
|
||||
// there is a possible flaw in the qca 2.0 api, in
|
||||
// that if sasl data is received from the peer
|
||||
// followed by a disconnect from the peer, there is
|
||||
// no clear approach to salvaging the bytes. tls is
|
||||
// not affected because tls has the concept of
|
||||
// closing a session. with sasl, there is no
|
||||
// closing, and since the qca api is asynchronous,
|
||||
// we could potentially wait forever for decoded
|
||||
// data, if the last write was a partial packet.
|
||||
//
|
||||
// for now, we can perform a simple workaround of
|
||||
// waiting at least three event loop cycles for
|
||||
// decoded data before giving up and assuming the
|
||||
// last write was partial. the fact is, all current
|
||||
// qca sasl providers respond within this time
|
||||
// frame, so this fix should work fine for now. in
|
||||
// qca 2.1, we should revise the api to handle this
|
||||
// situation better.
|
||||
//
|
||||
// further note: i guess this only affects application
|
||||
// protocols that have no close message of their
|
||||
// own, and rely on the tcp-level close. examples
|
||||
// are http, and of course this qcatest protocol.
|
||||
if(waitCycles == 0)
|
||||
{
|
||||
waitCycles = 3;
|
||||
QMetaObject::invokeMethod(this, "waitWriteIncoming", Qt::QueuedConnection);
|
||||
}
|
||||
// there is a possible flaw in the qca 2.0 api, in
|
||||
// that if sasl data is received from the peer
|
||||
// followed by a disconnect from the peer, there is
|
||||
// no clear approach to salvaging the bytes. tls is
|
||||
// not affected because tls has the concept of
|
||||
// closing a session. with sasl, there is no
|
||||
// closing, and since the qca api is asynchronous,
|
||||
// we could potentially wait forever for decoded
|
||||
// data, if the last write was a partial packet.
|
||||
//
|
||||
// for now, we can perform a simple workaround of
|
||||
// waiting at least three event loop cycles for
|
||||
// decoded data before giving up and assuming the
|
||||
// last write was partial. the fact is, all current
|
||||
// qca sasl providers respond within this time
|
||||
// frame, so this fix should work fine for now. in
|
||||
// qca 2.1, we should revise the api to handle this
|
||||
// situation better.
|
||||
//
|
||||
// further note: i guess this only affects application
|
||||
// protocols that have no close message of their
|
||||
// own, and rely on the tcp-level close. examples
|
||||
// are http, and of course this qcatest protocol.
|
||||
if (waitCycles == 0) {
|
||||
waitCycles = 3;
|
||||
QMetaObject::invokeMethod(this, "waitWriteIncoming", Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
sasl->writeIncoming(a);
|
||||
}
|
||||
else // mech list or sasl negotiation mode
|
||||
{
|
||||
if(sock->canReadLine())
|
||||
{
|
||||
QString line = sock->readLine();
|
||||
line.truncate(line.length() - 1); // chop the newline
|
||||
handleLine(line);
|
||||
}
|
||||
}
|
||||
}
|
||||
sasl->writeIncoming(a);
|
||||
} else // mech list or sasl negotiation mode
|
||||
{
|
||||
if (sock->canReadLine()) {
|
||||
QString line = QString::fromLatin1(sock->readLine());
|
||||
line.truncate(line.length() - 1); // chop the newline
|
||||
handleLine(line);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sasl_clientFirstStep(bool clientInit, const QByteArray &clientInitData)
|
||||
{
|
||||
printf("Choosing mech: %s\n", qPrintable(sasl->mechanism()));
|
||||
QString line = sasl->mechanism();
|
||||
if(clientInit)
|
||||
{
|
||||
line += ' ';
|
||||
line += arrayToString(clientInitData);
|
||||
}
|
||||
sendLine(line);
|
||||
}
|
||||
void sasl_clientFirstStep(bool clientInit, const QByteArray &clientInitData)
|
||||
{
|
||||
printf("Choosing mech: %s\n", qPrintable(sasl->mechanism()));
|
||||
QString line = sasl->mechanism();
|
||||
if (clientInit) {
|
||||
line += QLatin1Char(' ');
|
||||
line += arrayToString(clientInitData);
|
||||
}
|
||||
sendLine(line);
|
||||
}
|
||||
|
||||
void sasl_nextStep(const QByteArray &stepData)
|
||||
{
|
||||
QString line = "C";
|
||||
if(!stepData.isEmpty())
|
||||
{
|
||||
line += ',';
|
||||
line += arrayToString(stepData);
|
||||
}
|
||||
sendLine(line);
|
||||
}
|
||||
void sasl_nextStep(const QByteArray &stepData)
|
||||
{
|
||||
QString line = QStringLiteral("C");
|
||||
if (!stepData.isEmpty()) {
|
||||
line += QLatin1Char(',');
|
||||
line += arrayToString(stepData);
|
||||
}
|
||||
sendLine(line);
|
||||
}
|
||||
|
||||
void sasl_needParams(const QCA::SASL::Params ¶ms)
|
||||
{
|
||||
if(params.needUsername())
|
||||
{
|
||||
user = prompt("Username:");
|
||||
sasl->setUsername(user);
|
||||
}
|
||||
void sasl_needParams(const QCA::SASL::Params ¶ms)
|
||||
{
|
||||
if (params.needUsername()) {
|
||||
user = prompt(QStringLiteral("Username:"));
|
||||
sasl->setUsername(user);
|
||||
}
|
||||
|
||||
if(params.canSendAuthzid() && !no_authzid)
|
||||
{
|
||||
authzid = prompt("Authorize As (enter to skip):");
|
||||
if(!authzid.isEmpty())
|
||||
sasl->setAuthzid(authzid);
|
||||
}
|
||||
if (params.canSendAuthzid() && !no_authzid) {
|
||||
authzid = prompt(QStringLiteral("Authorize As (enter to skip):"));
|
||||
if (!authzid.isEmpty())
|
||||
sasl->setAuthzid(authzid);
|
||||
}
|
||||
|
||||
if(params.needPassword())
|
||||
{
|
||||
QCA::ConsolePrompt prompt;
|
||||
prompt.getHidden("* Password");
|
||||
prompt.waitForFinished();
|
||||
QCA::SecureArray pass = prompt.result();
|
||||
sasl->setPassword(pass);
|
||||
}
|
||||
if (params.needPassword()) {
|
||||
QCA::ConsolePrompt prompt;
|
||||
prompt.getHidden(QStringLiteral("* Password"));
|
||||
prompt.waitForFinished();
|
||||
QCA::SecureArray pass = prompt.result();
|
||||
sasl->setPassword(pass);
|
||||
}
|
||||
|
||||
if(params.canSendRealm() && !no_realm)
|
||||
{
|
||||
QStringList realms = sasl->realmList();
|
||||
printf("Available realms:\n");
|
||||
if(realms.isEmpty())
|
||||
printf(" (none specified)\n");
|
||||
foreach(const QString &s, realms)
|
||||
printf(" %s\n", qPrintable(s));
|
||||
realm = prompt("Realm (enter to skip):");
|
||||
if(!realm.isEmpty())
|
||||
sasl->setRealm(realm);
|
||||
}
|
||||
if (params.canSendRealm() && !no_realm) {
|
||||
QStringList realms = sasl->realmList();
|
||||
printf("Available realms:\n");
|
||||
if (realms.isEmpty())
|
||||
printf(" (none specified)\n");
|
||||
foreach (const QString &s, realms)
|
||||
printf(" %s\n", qPrintable(s));
|
||||
realm = prompt(QStringLiteral("Realm (enter to skip):"));
|
||||
if (!realm.isEmpty())
|
||||
sasl->setRealm(realm);
|
||||
}
|
||||
|
||||
sasl->continueAfterParams();
|
||||
}
|
||||
sasl->continueAfterParams();
|
||||
}
|
||||
|
||||
void sasl_authenticated()
|
||||
{
|
||||
printf("SASL success!\n");
|
||||
printf("SSF: %d\n", sasl->ssf());
|
||||
}
|
||||
void sasl_authenticated()
|
||||
{
|
||||
printf("SASL success!\n");
|
||||
printf("SSF: %d\n", sasl->ssf());
|
||||
}
|
||||
|
||||
void sasl_readyRead()
|
||||
{
|
||||
QByteArray a = sasl->read();
|
||||
inbuf += a;
|
||||
processInbuf();
|
||||
}
|
||||
void sasl_readyRead()
|
||||
{
|
||||
QByteArray a = sasl->read();
|
||||
inbuf += a;
|
||||
processInbuf();
|
||||
}
|
||||
|
||||
void sasl_readyReadOutgoing()
|
||||
{
|
||||
QByteArray a = sasl->readOutgoing();
|
||||
sock->write(a);
|
||||
}
|
||||
void sasl_readyReadOutgoing()
|
||||
{
|
||||
QByteArray a = sasl->readOutgoing();
|
||||
sock->write(a);
|
||||
}
|
||||
|
||||
void sasl_error()
|
||||
{
|
||||
int e = sasl->errorCode();
|
||||
if(e == QCA::SASL::ErrorInit)
|
||||
printf("Error: sasl: initialization failed.\n");
|
||||
else if(e == QCA::SASL::ErrorHandshake)
|
||||
printf("Error: sasl: %s.\n", qPrintable(saslAuthConditionToString(sasl->authCondition())));
|
||||
else if(e == QCA::SASL::ErrorCrypt)
|
||||
printf("Error: sasl: broken security layer.\n");
|
||||
else
|
||||
printf("Error: sasl: unknown error.\n");
|
||||
void sasl_error()
|
||||
{
|
||||
int e = sasl->errorCode();
|
||||
if (e == QCA::SASL::ErrorInit)
|
||||
printf("Error: sasl: initialization failed.\n");
|
||||
else if (e == QCA::SASL::ErrorHandshake)
|
||||
printf("Error: sasl: %s.\n", qPrintable(saslAuthConditionToString(sasl->authCondition())));
|
||||
else if (e == QCA::SASL::ErrorCrypt)
|
||||
printf("Error: sasl: broken security layer.\n");
|
||||
else
|
||||
printf("Error: sasl: unknown error.\n");
|
||||
|
||||
emit quit();
|
||||
}
|
||||
emit quit();
|
||||
}
|
||||
|
||||
void waitWriteIncoming()
|
||||
{
|
||||
--waitCycles;
|
||||
if(waitCycles > 0)
|
||||
{
|
||||
QMetaObject::invokeMethod(this, "waitWriteIncoming", Qt::QueuedConnection);
|
||||
return;
|
||||
}
|
||||
void waitWriteIncoming()
|
||||
{
|
||||
--waitCycles;
|
||||
if (waitCycles > 0) {
|
||||
QMetaObject::invokeMethod(this, "waitWriteIncoming", Qt::QueuedConnection);
|
||||
return;
|
||||
}
|
||||
|
||||
tryFinished();
|
||||
}
|
||||
tryFinished();
|
||||
}
|
||||
|
||||
private:
|
||||
void tryFinished()
|
||||
{
|
||||
if(sock_done && waitCycles == 0)
|
||||
{
|
||||
printf("Finished, server closed connection.\n");
|
||||
void tryFinished()
|
||||
{
|
||||
if (sock_done && waitCycles == 0) {
|
||||
printf("Finished, server closed connection.\n");
|
||||
|
||||
// if we give up on waiting for a response to
|
||||
// writeIncoming, then it might come late. in
|
||||
// theory this shouldn't happen if we wait enough
|
||||
// cycles, but if one were to arrive then it could
|
||||
// occur between the request to quit the app and
|
||||
// the actual quit of the app. to assist with
|
||||
// debugging, then, we'll explicitly stop listening
|
||||
// for signals here. otherwise the response may
|
||||
// still be received and displayed, giving a false
|
||||
// sense of correctness.
|
||||
sasl->disconnect(this);
|
||||
// if we give up on waiting for a response to
|
||||
// writeIncoming, then it might come late. in
|
||||
// theory this shouldn't happen if we wait enough
|
||||
// cycles, but if one were to arrive then it could
|
||||
// occur between the request to quit the app and
|
||||
// the actual quit of the app. to assist with
|
||||
// debugging, then, we'll explicitly stop listening
|
||||
// for signals here. otherwise the response may
|
||||
// still be received and displayed, giving a false
|
||||
// sense of correctness.
|
||||
sasl->disconnect(this);
|
||||
|
||||
emit quit();
|
||||
}
|
||||
}
|
||||
emit quit();
|
||||
}
|
||||
}
|
||||
|
||||
QString arrayToString(const QByteArray &ba)
|
||||
{
|
||||
return QCA::Base64().arrayToString(ba);
|
||||
}
|
||||
QString arrayToString(const QByteArray &ba)
|
||||
{
|
||||
return QCA::Base64().arrayToString(ba);
|
||||
}
|
||||
|
||||
QByteArray stringToArray(const QString &s)
|
||||
{
|
||||
return QCA::Base64().stringToArray(s).toByteArray();
|
||||
}
|
||||
QByteArray stringToArray(const QString &s)
|
||||
{
|
||||
return QCA::Base64().stringToArray(s).toByteArray();
|
||||
}
|
||||
|
||||
void sendLine(const QString &line)
|
||||
{
|
||||
printf("Writing: {%s}\n", qPrintable(line));
|
||||
QString s = line + '\n';
|
||||
QByteArray a = s.toUtf8();
|
||||
if(mode == 2) // app mode
|
||||
sasl->write(a); // write to sasl
|
||||
else // mech list or sasl negotiation
|
||||
sock->write(a); // write to socket
|
||||
}
|
||||
void sendLine(const QString &line)
|
||||
{
|
||||
printf("Writing: {%s}\n", qPrintable(line));
|
||||
QString s = line + QLatin1Char('\n');
|
||||
QByteArray a = s.toUtf8();
|
||||
if (mode == 2) // app mode
|
||||
sasl->write(a); // write to sasl
|
||||
else // mech list or sasl negotiation
|
||||
sock->write(a); // write to socket
|
||||
}
|
||||
|
||||
void processInbuf()
|
||||
{
|
||||
// collect completed lines from inbuf
|
||||
QStringList list;
|
||||
int at;
|
||||
while((at = inbuf.indexOf('\n')) != -1)
|
||||
{
|
||||
list += QString::fromUtf8(inbuf.mid(0, at));
|
||||
inbuf = inbuf.mid(at + 1);
|
||||
}
|
||||
void processInbuf()
|
||||
{
|
||||
// collect completed lines from inbuf
|
||||
QStringList list;
|
||||
int at;
|
||||
while ((at = inbuf.indexOf('\n')) != -1) {
|
||||
list += QString::fromUtf8(inbuf.mid(0, at));
|
||||
inbuf = inbuf.mid(at + 1);
|
||||
}
|
||||
|
||||
// process the lines
|
||||
foreach(const QString &line, list)
|
||||
handleLine(line);
|
||||
}
|
||||
// process the lines
|
||||
foreach (const QString &line, list)
|
||||
handleLine(line);
|
||||
}
|
||||
|
||||
void handleLine(const QString &line)
|
||||
{
|
||||
printf("Reading: [%s]\n", qPrintable(line));
|
||||
if(mode == 0)
|
||||
{
|
||||
// first line is the method list
|
||||
QStringList mechlist = line.split(' ');
|
||||
mode = 1; // switch to sasl negotiation mode
|
||||
sasl->startClient(proto, host, mechlist);
|
||||
}
|
||||
else if(mode == 1)
|
||||
{
|
||||
QString type, rest;
|
||||
int n = line.indexOf(',');
|
||||
if(n != -1)
|
||||
{
|
||||
type = line.mid(0, n);
|
||||
rest = line.mid(n + 1);
|
||||
}
|
||||
else
|
||||
type = line;
|
||||
|
||||
if(type == "C")
|
||||
{
|
||||
sasl->putStep(stringToArray(rest));
|
||||
}
|
||||
else if(type == "E")
|
||||
{
|
||||
if(!rest.isEmpty())
|
||||
printf("Error: server says: %s.\n", qPrintable(rest));
|
||||
else
|
||||
printf("Error: server error, unspecified.\n");
|
||||
emit quit();
|
||||
return;
|
||||
}
|
||||
else if(type == "A")
|
||||
{
|
||||
printf("Authentication success.\n");
|
||||
mode = 2; // switch to app mode
|
||||
void handleLine(const QString &line)
|
||||
{
|
||||
printf("Reading: [%s]\n", qPrintable(line));
|
||||
if (mode == 0) {
|
||||
// first line is the method list
|
||||
const QStringList mechlist = line.split(QLatin1Char(' '));
|
||||
mode = 1; // switch to sasl negotiation mode
|
||||
sasl->startClient(proto, host, mechlist);
|
||||
} else if (mode == 1) {
|
||||
QString type, rest;
|
||||
int n = line.indexOf(QLatin1Char(','));
|
||||
if (n != -1) {
|
||||
type = line.mid(0, n);
|
||||
rest = line.mid(n + 1);
|
||||
} else
|
||||
type = line;
|
||||
|
||||
// at this point, the server may send us text
|
||||
// lines for us to display and then close.
|
||||
if (type == QLatin1String("C")) {
|
||||
sasl->putStep(stringToArray(rest));
|
||||
} else if (type == QLatin1String("E")) {
|
||||
if (!rest.isEmpty())
|
||||
printf("Error: server says: %s.\n", qPrintable(rest));
|
||||
else
|
||||
printf("Error: server error, unspecified.\n");
|
||||
emit quit();
|
||||
return;
|
||||
} else if (type == QLatin1String("A")) {
|
||||
printf("Authentication success.\n");
|
||||
mode = 2; // switch to app mode
|
||||
|
||||
sock_readyRead(); // any extra data?
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Error: Bad format from peer, closing.\n");
|
||||
emit quit();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
// at this point, the server may send us text
|
||||
// lines for us to display and then close.
|
||||
|
||||
sock_readyRead(); // any extra data?
|
||||
return;
|
||||
} else {
|
||||
printf("Error: Bad format from peer, closing.\n");
|
||||
emit quit();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void usage()
|
||||
{
|
||||
printf("usage: saslclient (options) host(:port) (user) (pass)\n");
|
||||
printf("options: --proto=x, --authzid=x, --realm=x\n");
|
||||
printf("usage: saslclient (options) host(:port) (user) (pass)\n");
|
||||
printf("options: --proto=x, --authzid=x, --realm=x\n");
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
QCA::Initializer init;
|
||||
QCoreApplication qapp(argc, argv);
|
||||
QCA::Initializer init;
|
||||
QCoreApplication qapp(argc, argv);
|
||||
|
||||
QStringList args = qapp.arguments();
|
||||
args.removeFirst();
|
||||
QStringList args = qapp.arguments();
|
||||
args.removeFirst();
|
||||
|
||||
// options
|
||||
QString proto = "qcatest"; // default protocol
|
||||
QString authzid, realm;
|
||||
bool no_authzid = false;
|
||||
bool no_realm = false;
|
||||
for(int n = 0; n < args.count(); ++n)
|
||||
{
|
||||
if(!args[n].startsWith("--"))
|
||||
continue;
|
||||
// options
|
||||
QString proto = QStringLiteral("qcatest"); // default protocol
|
||||
QString authzid, realm;
|
||||
bool no_authzid = false;
|
||||
bool no_realm = false;
|
||||
for (int n = 0; n < args.count(); ++n) {
|
||||
if (!args[n].startsWith(QLatin1String("--")))
|
||||
continue;
|
||||
|
||||
QString opt = args[n].mid(2);
|
||||
QString var, val;
|
||||
int at = opt.indexOf('=');
|
||||
if(at != -1)
|
||||
{
|
||||
var = opt.mid(0, at);
|
||||
val = opt.mid(at + 1);
|
||||
}
|
||||
else
|
||||
var = opt;
|
||||
QString opt = args[n].mid(2);
|
||||
QString var, val;
|
||||
int at = opt.indexOf(QLatin1Char('='));
|
||||
if (at != -1) {
|
||||
var = opt.mid(0, at);
|
||||
val = opt.mid(at + 1);
|
||||
} else
|
||||
var = opt;
|
||||
|
||||
if(var == "proto")
|
||||
{
|
||||
proto = val;
|
||||
}
|
||||
else if(var == "authzid")
|
||||
{
|
||||
// specifying empty authzid means force unspecified
|
||||
if(val.isEmpty())
|
||||
no_authzid = true;
|
||||
else
|
||||
authzid = val;
|
||||
}
|
||||
else if(var == "realm")
|
||||
{
|
||||
// specifying empty realm means force unspecified
|
||||
if(val.isEmpty())
|
||||
no_realm = true;
|
||||
else
|
||||
realm = val;
|
||||
}
|
||||
if (var == QLatin1String("proto")) {
|
||||
proto = val;
|
||||
} else if (var == QLatin1String("authzid")) {
|
||||
// specifying empty authzid means force unspecified
|
||||
if (val.isEmpty())
|
||||
no_authzid = true;
|
||||
else
|
||||
authzid = val;
|
||||
} else if (var == QLatin1String("realm")) {
|
||||
// specifying empty realm means force unspecified
|
||||
if (val.isEmpty())
|
||||
no_realm = true;
|
||||
else
|
||||
realm = val;
|
||||
}
|
||||
|
||||
args.removeAt(n);
|
||||
--n; // adjust position
|
||||
}
|
||||
args.removeAt(n);
|
||||
--n; // adjust position
|
||||
}
|
||||
|
||||
if(args.count() < 1)
|
||||
{
|
||||
usage();
|
||||
return 0;
|
||||
}
|
||||
if (args.count() < 1) {
|
||||
usage();
|
||||
return 0;
|
||||
}
|
||||
|
||||
QString host, user, pass;
|
||||
int port = 8001; // default port
|
||||
QString host, user, pass;
|
||||
int port = 8001; // default port
|
||||
|
||||
QString hostinput = args[0];
|
||||
if(args.count() >= 2)
|
||||
user = args[1];
|
||||
if(args.count() >= 3)
|
||||
pass = args[2];
|
||||
QString hostinput = args[0];
|
||||
if (args.count() >= 2)
|
||||
user = args[1];
|
||||
if (args.count() >= 3)
|
||||
pass = args[2];
|
||||
|
||||
int at = hostinput.indexOf(':');
|
||||
if(at != -1)
|
||||
{
|
||||
host = hostinput.mid(0, at);
|
||||
port = hostinput.mid(at + 1).toInt();
|
||||
}
|
||||
else
|
||||
host = hostinput;
|
||||
int at = hostinput.indexOf(QLatin1Char(':'));
|
||||
if (at != -1) {
|
||||
host = hostinput.mid(0, at);
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 2)
|
||||
port = QStringView(hostinput).mid(at + 1).toInt();
|
||||
#else
|
||||
port = hostinput.midRef(at + 1).toInt();
|
||||
#endif
|
||||
} else
|
||||
host = hostinput;
|
||||
|
||||
if(!QCA::isSupported("sasl"))
|
||||
{
|
||||
printf("Error: SASL support not found.\n");
|
||||
return 1;
|
||||
}
|
||||
if (!QCA::isSupported("sasl")) {
|
||||
printf("Error: SASL support not found.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
ClientTest client(host, port, proto, authzid, realm, user, pass, no_authzid, no_realm);
|
||||
QObject::connect(&client, SIGNAL(quit()), &qapp, SLOT(quit()));
|
||||
QTimer::singleShot(0, &client, SLOT(start()));
|
||||
qapp.exec();
|
||||
ClientTest client(host, port, proto, authzid, realm, user, pass, no_authzid, no_realm);
|
||||
QObject::connect(&client, &ClientTest::quit, &qapp, &QCoreApplication::quit);
|
||||
QTimer::singleShot(0, &client, &ClientTest::start);
|
||||
qapp.exec();
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include "saslclient.moc"
|
||||
|
@ -1,8 +1,10 @@
|
||||
set(saslserver_bin_SRCS saslserver.cpp)
|
||||
|
||||
MY_AUTOMOC( saslserver_bin_SRCS)
|
||||
|
||||
add_executable(saslserver ${saslserver_bin_SRCS})
|
||||
|
||||
target_link_qca_libraries(saslserver)
|
||||
target_link_libraries(saslserver ${QT_QTNETWORK_LIBRARY})
|
||||
if(QT6)
|
||||
target_link_libraries(saslserver Qt6::Network)
|
||||
else()
|
||||
target_link_libraries(saslserver Qt5::Network)
|
||||
endif()
|
||||
|
@ -21,10 +21,10 @@
|
||||
*/
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QTimer>
|
||||
#include <QTcpSocket>
|
||||
#include <QTcpServer>
|
||||
#include <stdio.h>
|
||||
#include <QTcpSocket>
|
||||
#include <QTimer>
|
||||
#include <cstdio>
|
||||
|
||||
// QtCrypto has the declarations for all of QCA
|
||||
#include <QtCrypto>
|
||||
@ -35,480 +35,490 @@
|
||||
|
||||
static QString socketErrorToString(QAbstractSocket::SocketError x)
|
||||
{
|
||||
QString s;
|
||||
switch(x)
|
||||
{
|
||||
case QAbstractSocket::ConnectionRefusedError:
|
||||
s = "connection refused or timed out"; break;
|
||||
case QAbstractSocket::RemoteHostClosedError:
|
||||
s = "remote host closed the connection"; break;
|
||||
case QAbstractSocket::HostNotFoundError:
|
||||
s = "host not found"; break;
|
||||
case QAbstractSocket::SocketAccessError:
|
||||
s = "access error"; break;
|
||||
case QAbstractSocket::SocketResourceError:
|
||||
s = "too many sockets"; break;
|
||||
case QAbstractSocket::SocketTimeoutError:
|
||||
s = "operation timed out"; break;
|
||||
case QAbstractSocket::DatagramTooLargeError:
|
||||
s = "datagram was larger than system limit"; break;
|
||||
case QAbstractSocket::NetworkError:
|
||||
s = "network error"; break;
|
||||
case QAbstractSocket::AddressInUseError:
|
||||
s = "address is already in use"; break;
|
||||
case QAbstractSocket::SocketAddressNotAvailableError:
|
||||
s = "address does not belong to the host"; break;
|
||||
case QAbstractSocket::UnsupportedSocketOperationError:
|
||||
s = "operation is not supported by the local operating system"; break;
|
||||
default:
|
||||
s = "unknown socket error"; break;
|
||||
}
|
||||
return s;
|
||||
QString s;
|
||||
switch (x) {
|
||||
case QAbstractSocket::ConnectionRefusedError:
|
||||
s = QStringLiteral("connection refused or timed out");
|
||||
break;
|
||||
case QAbstractSocket::RemoteHostClosedError:
|
||||
s = QStringLiteral("remote host closed the connection");
|
||||
break;
|
||||
case QAbstractSocket::HostNotFoundError:
|
||||
s = QStringLiteral("host not found");
|
||||
break;
|
||||
case QAbstractSocket::SocketAccessError:
|
||||
s = QStringLiteral("access error");
|
||||
break;
|
||||
case QAbstractSocket::SocketResourceError:
|
||||
s = QStringLiteral("too many sockets");
|
||||
break;
|
||||
case QAbstractSocket::SocketTimeoutError:
|
||||
s = QStringLiteral("operation timed out");
|
||||
break;
|
||||
case QAbstractSocket::DatagramTooLargeError:
|
||||
s = QStringLiteral("datagram was larger than system limit");
|
||||
break;
|
||||
case QAbstractSocket::NetworkError:
|
||||
s = QStringLiteral("network error");
|
||||
break;
|
||||
case QAbstractSocket::AddressInUseError:
|
||||
s = QStringLiteral("address is already in use");
|
||||
break;
|
||||
case QAbstractSocket::SocketAddressNotAvailableError:
|
||||
s = QStringLiteral("address does not belong to the host");
|
||||
break;
|
||||
case QAbstractSocket::UnsupportedSocketOperationError:
|
||||
s = QStringLiteral("operation is not supported by the local operating system");
|
||||
break;
|
||||
default:
|
||||
s = QStringLiteral("unknown socket error");
|
||||
break;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
static QString saslAuthConditionToString(QCA::SASL::AuthCondition x)
|
||||
{
|
||||
QString s;
|
||||
switch(x)
|
||||
{
|
||||
case QCA::SASL::NoMechanism:
|
||||
s = "no appropriate mechanism could be negotiated"; break;
|
||||
case QCA::SASL::BadProtocol:
|
||||
s = "bad SASL protocol"; break;
|
||||
case QCA::SASL::BadAuth:
|
||||
s = "authentication failed"; break;
|
||||
case QCA::SASL::NoAuthzid:
|
||||
s = "authorization failed"; break;
|
||||
case QCA::SASL::TooWeak:
|
||||
s = "mechanism too weak for this user"; break;
|
||||
case QCA::SASL::NeedEncrypt:
|
||||
s = "encryption is needed to use this mechanism"; break;
|
||||
case QCA::SASL::Expired:
|
||||
s = "passphrase expired"; break;
|
||||
case QCA::SASL::Disabled:
|
||||
s = "account is disabled"; break;
|
||||
case QCA::SASL::NoUser:
|
||||
s = "user not found"; break;
|
||||
case QCA::SASL::RemoteUnavailable:
|
||||
s = "needed remote service is unavailable"; break;
|
||||
// AuthFail or unknown (including those defined for client only)
|
||||
default:
|
||||
s = "generic authentication failure"; break;
|
||||
};
|
||||
return s;
|
||||
QString s;
|
||||
switch (x) {
|
||||
case QCA::SASL::NoMechanism:
|
||||
s = QStringLiteral("no appropriate mechanism could be negotiated");
|
||||
break;
|
||||
case QCA::SASL::BadProtocol:
|
||||
s = QStringLiteral("bad SASL protocol");
|
||||
break;
|
||||
case QCA::SASL::BadAuth:
|
||||
s = QStringLiteral("authentication failed");
|
||||
break;
|
||||
case QCA::SASL::NoAuthzid:
|
||||
s = QStringLiteral("authorization failed");
|
||||
break;
|
||||
case QCA::SASL::TooWeak:
|
||||
s = QStringLiteral("mechanism too weak for this user");
|
||||
break;
|
||||
case QCA::SASL::NeedEncrypt:
|
||||
s = QStringLiteral("encryption is needed to use this mechanism");
|
||||
break;
|
||||
case QCA::SASL::Expired:
|
||||
s = QStringLiteral("passphrase expired");
|
||||
break;
|
||||
case QCA::SASL::Disabled:
|
||||
s = QStringLiteral("account is disabled");
|
||||
break;
|
||||
case QCA::SASL::NoUser:
|
||||
s = QStringLiteral("user not found");
|
||||
break;
|
||||
case QCA::SASL::RemoteUnavailable:
|
||||
s = QStringLiteral("needed remote service is unavailable");
|
||||
break;
|
||||
// AuthFail or unknown (including those defined for client only)
|
||||
default:
|
||||
s = QStringLiteral("generic authentication failure");
|
||||
break;
|
||||
};
|
||||
return s;
|
||||
}
|
||||
|
||||
// --- ServerTest declaration
|
||||
|
||||
class ServerTest : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
QString host, proto, realm, str;
|
||||
int port;
|
||||
QTcpServer *tcpServer;
|
||||
QList<int> ids;
|
||||
QString host, proto, realm, str;
|
||||
int port;
|
||||
QTcpServer *tcpServer;
|
||||
QList<int> ids;
|
||||
|
||||
public:
|
||||
ServerTest(const QString &_host, int _port, const QString &_proto, const QString &_realm, const QString &_str);
|
||||
ServerTest(const QString &_host, int _port, const QString &_proto, const QString &_realm, const QString &_str);
|
||||
|
||||
int reserveId();
|
||||
void releaseId(int id);
|
||||
int reserveId();
|
||||
void releaseId(int id);
|
||||
|
||||
public slots:
|
||||
void start();
|
||||
public Q_SLOTS:
|
||||
void start();
|
||||
|
||||
signals:
|
||||
void quit();
|
||||
Q_SIGNALS:
|
||||
void quit();
|
||||
|
||||
private slots:
|
||||
void server_newConnection();
|
||||
private Q_SLOTS:
|
||||
void server_newConnection();
|
||||
};
|
||||
|
||||
// --- ServerTestHandler
|
||||
|
||||
class ServerTestHandler : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
ServerTest *serverTest;
|
||||
QTcpSocket *sock;
|
||||
QCA::SASL *sasl;
|
||||
int id;
|
||||
QString host, proto, realm, str;
|
||||
int mode; // 0 = receive mechanism list, 1 = sasl negotiation, 2 = app
|
||||
int toWrite;
|
||||
ServerTest *serverTest;
|
||||
QTcpSocket *sock;
|
||||
QCA::SASL * sasl;
|
||||
int id;
|
||||
QString host, proto, realm, str;
|
||||
int mode; // 0 = receive mechanism list, 1 = sasl negotiation, 2 = app
|
||||
int toWrite;
|
||||
|
||||
public:
|
||||
ServerTestHandler(ServerTest *_serverTest, QTcpSocket *_sock, const QString &_host, const QString &_proto, const QString &_realm, const QString &_str) :
|
||||
serverTest(_serverTest),
|
||||
sock(_sock),
|
||||
host(_host),
|
||||
proto(_proto),
|
||||
realm(_realm),
|
||||
str(_str)
|
||||
{
|
||||
id = serverTest->reserveId();
|
||||
ServerTestHandler(ServerTest * _serverTest,
|
||||
QTcpSocket * _sock,
|
||||
const QString &_host,
|
||||
const QString &_proto,
|
||||
const QString &_realm,
|
||||
const QString &_str)
|
||||
: serverTest(_serverTest)
|
||||
, sock(_sock)
|
||||
, host(_host)
|
||||
, proto(_proto)
|
||||
, realm(_realm)
|
||||
, str(_str)
|
||||
{
|
||||
id = serverTest->reserveId();
|
||||
|
||||
sock->setParent(this);
|
||||
connect(sock, SIGNAL(disconnected()), SLOT(sock_disconnected()));
|
||||
connect(sock, SIGNAL(readyRead()), SLOT(sock_readyRead()));
|
||||
connect(sock, SIGNAL(error(QAbstractSocket::SocketError)), SLOT(sock_error(QAbstractSocket::SocketError)));
|
||||
connect(sock, SIGNAL(bytesWritten(qint64)), SLOT(sock_bytesWritten(qint64)));
|
||||
sock->setParent(this);
|
||||
connect(sock, &QTcpSocket::disconnected, this, &ServerTestHandler::sock_disconnected);
|
||||
connect(sock, &QTcpSocket::readyRead, this, &ServerTestHandler::sock_readyRead);
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
|
||||
connect(sock, &QTcpSocket::errorOccurred, this, &ServerTestHandler::sock_error);
|
||||
#else
|
||||
connect(sock,
|
||||
QOverload<QAbstractSocket::SocketError>::of(&QTcpSocket::error),
|
||||
this,
|
||||
&ServerTestHandler::sock_error);
|
||||
#endif
|
||||
connect(sock, &QTcpSocket::bytesWritten, this, &ServerTestHandler::sock_bytesWritten);
|
||||
|
||||
sasl = new QCA::SASL(this);
|
||||
connect(sasl, SIGNAL(authCheck(const QString &, const QString &)), SLOT(sasl_authCheck(const QString &, const QString &)));
|
||||
connect(sasl, SIGNAL(nextStep(const QByteArray &)), SLOT(sasl_nextStep(const QByteArray &)));
|
||||
connect(sasl, SIGNAL(authenticated()), SLOT(sasl_authenticated()));
|
||||
connect(sasl, SIGNAL(readyRead()), SLOT(sasl_readyRead()));
|
||||
connect(sasl, SIGNAL(readyReadOutgoing()), SLOT(sasl_readyReadOutgoing()));
|
||||
connect(sasl, SIGNAL(error()), SLOT(sasl_error()));
|
||||
connect(sasl, SIGNAL(serverStarted()), SLOT(sasl_serverStarted()));
|
||||
sasl = new QCA::SASL(this);
|
||||
connect(sasl, &QCA::SASL::authCheck, this, &ServerTestHandler::sasl_authCheck);
|
||||
connect(sasl, &QCA::SASL::nextStep, this, &ServerTestHandler::sasl_nextStep);
|
||||
connect(sasl, &QCA::SASL::authenticated, this, &ServerTestHandler::sasl_authenticated);
|
||||
connect(sasl, &QCA::SASL::readyRead, this, &ServerTestHandler::sasl_readyRead);
|
||||
connect(sasl, &QCA::SASL::readyReadOutgoing, this, &ServerTestHandler::sasl_readyReadOutgoing);
|
||||
connect(sasl, &QCA::SASL::error, this, &ServerTestHandler::sasl_error);
|
||||
connect(sasl, &QCA::SASL::serverStarted, this, &ServerTestHandler::sasl_serverStarted);
|
||||
|
||||
mode = 0; // mech list mode
|
||||
toWrite = 0;
|
||||
mode = 0; // mech list mode
|
||||
toWrite = 0;
|
||||
|
||||
int flags = 0;
|
||||
flags |= QCA::SASL::AllowPlain;
|
||||
flags |= QCA::SASL::AllowAnonymous;
|
||||
sasl->setConstraints((QCA::SASL::AuthFlags)flags, 0, 256);
|
||||
int flags = 0;
|
||||
flags |= QCA::SASL::AllowPlain;
|
||||
flags |= QCA::SASL::AllowAnonymous;
|
||||
sasl->setConstraints((QCA::SASL::AuthFlags)flags, 0, 256);
|
||||
|
||||
printf("%d: Connection received! Starting SASL handshake...\n", id);
|
||||
sasl->startServer(proto, host, realm);
|
||||
}
|
||||
printf("%d: Connection received! Starting SASL handshake...\n", id);
|
||||
sasl->startServer(proto, host, realm);
|
||||
}
|
||||
|
||||
~ServerTestHandler()
|
||||
{
|
||||
serverTest->releaseId(id);
|
||||
}
|
||||
~ServerTestHandler() override
|
||||
{
|
||||
serverTest->releaseId(id);
|
||||
}
|
||||
|
||||
private slots:
|
||||
void sasl_serverStarted()
|
||||
{
|
||||
sendLine(sasl->mechanismList().join(" "));
|
||||
}
|
||||
private Q_SLOTS:
|
||||
void sasl_serverStarted()
|
||||
{
|
||||
sendLine(sasl->mechanismList().join(QStringLiteral(" ")));
|
||||
}
|
||||
|
||||
void sock_disconnected()
|
||||
{
|
||||
printf("%d: Connection closed.\n", id);
|
||||
discard();
|
||||
}
|
||||
void sock_disconnected()
|
||||
{
|
||||
printf("%d: Connection closed.\n", id);
|
||||
discard();
|
||||
}
|
||||
|
||||
void sock_error(QAbstractSocket::SocketError x)
|
||||
{
|
||||
if(x == QAbstractSocket::RemoteHostClosedError)
|
||||
{
|
||||
printf("%d: Error: client closed connection unexpectedly.\n", id);
|
||||
discard();
|
||||
return;
|
||||
}
|
||||
void sock_error(QAbstractSocket::SocketError x)
|
||||
{
|
||||
if (x == QAbstractSocket::RemoteHostClosedError) {
|
||||
printf("%d: Error: client closed connection unexpectedly.\n", id);
|
||||
discard();
|
||||
return;
|
||||
}
|
||||
|
||||
printf("%d: Error: socket: %s\n", id, qPrintable(socketErrorToString(x)));
|
||||
discard();
|
||||
}
|
||||
printf("%d: Error: socket: %s\n", id, qPrintable(socketErrorToString(x)));
|
||||
discard();
|
||||
}
|
||||
|
||||
void sock_readyRead()
|
||||
{
|
||||
if(sock->canReadLine())
|
||||
{
|
||||
QString line = sock->readLine();
|
||||
line.truncate(line.length() - 1); // chop the newline
|
||||
handleLine(line);
|
||||
}
|
||||
}
|
||||
void sock_readyRead()
|
||||
{
|
||||
if (sock->canReadLine()) {
|
||||
QString line = QString::fromLatin1(sock->readLine());
|
||||
line.truncate(line.length() - 1); // chop the newline
|
||||
handleLine(line);
|
||||
}
|
||||
}
|
||||
|
||||
void sock_bytesWritten(qint64 x)
|
||||
{
|
||||
if(mode == 2) // app mode
|
||||
{
|
||||
toWrite -= sasl->convertBytesWritten(x);
|
||||
if(toWrite == 0)
|
||||
{
|
||||
printf("%d: Sent, closing.\n", id);
|
||||
sock->close();
|
||||
}
|
||||
}
|
||||
}
|
||||
void sock_bytesWritten(qint64 x)
|
||||
{
|
||||
if (mode == 2) // app mode
|
||||
{
|
||||
toWrite -= sasl->convertBytesWritten(x);
|
||||
if (toWrite == 0) {
|
||||
printf("%d: Sent, closing.\n", id);
|
||||
sock->close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sasl_nextStep(const QByteArray &stepData)
|
||||
{
|
||||
QString line = "C";
|
||||
if(!stepData.isEmpty())
|
||||
{
|
||||
line += ',';
|
||||
line += arrayToString(stepData);
|
||||
}
|
||||
sendLine(line);
|
||||
}
|
||||
void sasl_nextStep(const QByteArray &stepData)
|
||||
{
|
||||
QString line = QStringLiteral("C");
|
||||
if (!stepData.isEmpty()) {
|
||||
line += QLatin1Char(',');
|
||||
line += arrayToString(stepData);
|
||||
}
|
||||
sendLine(line);
|
||||
}
|
||||
|
||||
void sasl_authCheck(const QString &user, const QString &authzid)
|
||||
{
|
||||
printf("%d: AuthCheck: User: [%s], Authzid: [%s]\n", id, qPrintable(user), qPrintable(authzid));
|
||||
void sasl_authCheck(const QString &user, const QString &authzid)
|
||||
{
|
||||
printf("%d: AuthCheck: User: [%s], Authzid: [%s]\n", id, qPrintable(user), qPrintable(authzid));
|
||||
|
||||
// user - who has logged in, confirmed by sasl
|
||||
// authzid - the identity the user wishes to act as, which
|
||||
// could be another user or just any arbitrary string (in
|
||||
// XMPP, this field holds a Jabber ID, for example). this
|
||||
// field is not necessarily confirmed by sasl, and the
|
||||
// decision about whether the user can act as the authzid
|
||||
// must be made by the app.
|
||||
// user - who has logged in, confirmed by sasl
|
||||
// authzid - the identity the user wishes to act as, which
|
||||
// could be another user or just any arbitrary string (in
|
||||
// XMPP, this field holds a Jabber ID, for example). this
|
||||
// field is not necessarily confirmed by sasl, and the
|
||||
// decision about whether the user can act as the authzid
|
||||
// must be made by the app.
|
||||
|
||||
// for this simple example program, we allow anyone to use
|
||||
// the service, and simply continue onward with the
|
||||
// negotiation.
|
||||
sasl->continueAfterAuthCheck();
|
||||
}
|
||||
// for this simple example program, we allow anyone to use
|
||||
// the service, and simply continue onward with the
|
||||
// negotiation.
|
||||
sasl->continueAfterAuthCheck();
|
||||
}
|
||||
|
||||
void sasl_authenticated()
|
||||
{
|
||||
sendLine("A");
|
||||
printf("%d: Authentication success.\n", id);
|
||||
mode = 2; // switch to app mode
|
||||
printf("%d: SSF: %d\n", id, sasl->ssf());
|
||||
sendLine(str);
|
||||
}
|
||||
void sasl_authenticated()
|
||||
{
|
||||
sendLine(QStringLiteral("A"));
|
||||
printf("%d: Authentication success.\n", id);
|
||||
mode = 2; // switch to app mode
|
||||
printf("%d: SSF: %d\n", id, sasl->ssf());
|
||||
sendLine(str);
|
||||
}
|
||||
|
||||
void sasl_readyRead()
|
||||
{
|
||||
QByteArray a = sasl->read();
|
||||
printf("%d: Warning, client sent %d bytes unexpectedly.\n", id, a.size());
|
||||
}
|
||||
void sasl_readyRead()
|
||||
{
|
||||
QByteArray a = sasl->read();
|
||||
printf("%d: Warning, client sent %d bytes unexpectedly.\n", id, int(a.size()));
|
||||
}
|
||||
|
||||
void sasl_readyReadOutgoing()
|
||||
{
|
||||
sock->write(sasl->readOutgoing());
|
||||
}
|
||||
void sasl_readyReadOutgoing()
|
||||
{
|
||||
sock->write(sasl->readOutgoing());
|
||||
}
|
||||
|
||||
void sasl_error()
|
||||
{
|
||||
int e = sasl->errorCode();
|
||||
if(e == QCA::SASL::ErrorInit)
|
||||
{
|
||||
printf("%d: Error: sasl: initialization failed.\n", id);
|
||||
}
|
||||
else if(e == QCA::SASL::ErrorHandshake)
|
||||
{
|
||||
QString errstr = saslAuthConditionToString(sasl->authCondition());
|
||||
sendLine(QString("E,") + errstr);
|
||||
printf("%d: Error: sasl: %s.\n", id, qPrintable(errstr));
|
||||
}
|
||||
else if(e == QCA::SASL::ErrorCrypt)
|
||||
{
|
||||
printf("%d: Error: sasl: broken security layer.\n", id);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("%d: Error: sasl: unknown error.\n", id);
|
||||
}
|
||||
void sasl_error()
|
||||
{
|
||||
int e = sasl->errorCode();
|
||||
if (e == QCA::SASL::ErrorInit) {
|
||||
printf("%d: Error: sasl: initialization failed.\n", id);
|
||||
} else if (e == QCA::SASL::ErrorHandshake) {
|
||||
QString errstr = saslAuthConditionToString(sasl->authCondition());
|
||||
sendLine(QStringLiteral("E,") + errstr);
|
||||
printf("%d: Error: sasl: %s.\n", id, qPrintable(errstr));
|
||||
} else if (e == QCA::SASL::ErrorCrypt) {
|
||||
printf("%d: Error: sasl: broken security layer.\n", id);
|
||||
} else {
|
||||
printf("%d: Error: sasl: unknown error.\n", id);
|
||||
}
|
||||
|
||||
sock->close();
|
||||
}
|
||||
sock->close();
|
||||
}
|
||||
|
||||
private:
|
||||
void discard()
|
||||
{
|
||||
deleteLater();
|
||||
}
|
||||
void discard()
|
||||
{
|
||||
deleteLater();
|
||||
}
|
||||
|
||||
void handleLine(const QString &line)
|
||||
{
|
||||
printf("%d: Reading: [%s]\n", id, qPrintable(line));
|
||||
if(mode == 0)
|
||||
{
|
||||
int n = line.indexOf(' ');
|
||||
if(n != -1)
|
||||
{
|
||||
QString mech = line.mid(0, n);
|
||||
QString rest = line.mid(n + 1).toUtf8();
|
||||
sasl->putServerFirstStep(mech, stringToArray(rest));
|
||||
}
|
||||
else
|
||||
sasl->putServerFirstStep(line);
|
||||
++mode;
|
||||
}
|
||||
else if(mode == 1)
|
||||
{
|
||||
QString type, rest;
|
||||
int n = line.indexOf(',');
|
||||
if(n != -1)
|
||||
{
|
||||
type = line.mid(0, n);
|
||||
rest = line.mid(n + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
type = line;
|
||||
rest = "";
|
||||
}
|
||||
void handleLine(const QString &line)
|
||||
{
|
||||
printf("%d: Reading: [%s]\n", id, qPrintable(line));
|
||||
if (mode == 0) {
|
||||
int n = line.indexOf(QLatin1Char(' '));
|
||||
if (n != -1) {
|
||||
QString mech = line.mid(0, n);
|
||||
QString rest = QString::fromLatin1(line.mid(n + 1).toUtf8());
|
||||
sasl->putServerFirstStep(mech, stringToArray(rest));
|
||||
} else
|
||||
sasl->putServerFirstStep(line);
|
||||
++mode;
|
||||
} else if (mode == 1) {
|
||||
QString type, rest;
|
||||
int n = line.indexOf(QLatin1Char(','));
|
||||
if (n != -1) {
|
||||
type = line.mid(0, n);
|
||||
rest = line.mid(n + 1);
|
||||
} else {
|
||||
type = line;
|
||||
rest = QLatin1String("");
|
||||
}
|
||||
|
||||
if(type == "C")
|
||||
{
|
||||
sasl->putStep(stringToArray(rest));
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("%d: Bad format from peer, closing.\n", id);
|
||||
sock->close();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (type == QLatin1String("C")) {
|
||||
sasl->putStep(stringToArray(rest));
|
||||
} else {
|
||||
printf("%d: Bad format from peer, closing.\n", id);
|
||||
sock->close();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QString arrayToString(const QByteArray &ba)
|
||||
{
|
||||
QCA::Base64 encoder;
|
||||
return encoder.arrayToString(ba);
|
||||
}
|
||||
QString arrayToString(const QByteArray &ba)
|
||||
{
|
||||
QCA::Base64 encoder;
|
||||
return encoder.arrayToString(ba);
|
||||
}
|
||||
|
||||
QByteArray stringToArray(const QString &s)
|
||||
{
|
||||
QCA::Base64 decoder(QCA::Decode);
|
||||
return decoder.stringToArray(s).toByteArray();
|
||||
}
|
||||
QByteArray stringToArray(const QString &s)
|
||||
{
|
||||
QCA::Base64 decoder(QCA::Decode);
|
||||
return decoder.stringToArray(s).toByteArray();
|
||||
}
|
||||
|
||||
void sendLine(const QString &line)
|
||||
{
|
||||
printf("%d: Writing: {%s}\n", id, qPrintable(line));
|
||||
QString s = line + '\n';
|
||||
QByteArray a = s.toUtf8();
|
||||
if(mode == 2) // app mode
|
||||
{
|
||||
toWrite += a.size();
|
||||
sasl->write(a); // write to sasl
|
||||
}
|
||||
else // mech list or sasl negotiation
|
||||
sock->write(a); // write to socket
|
||||
}
|
||||
void sendLine(const QString &line)
|
||||
{
|
||||
printf("%d: Writing: {%s}\n", id, qPrintable(line));
|
||||
QString s = line + QLatin1Char('\n');
|
||||
QByteArray a = s.toUtf8();
|
||||
if (mode == 2) // app mode
|
||||
{
|
||||
toWrite += a.size();
|
||||
sasl->write(a); // write to sasl
|
||||
} else // mech list or sasl negotiation
|
||||
sock->write(a); // write to socket
|
||||
}
|
||||
};
|
||||
|
||||
// --- ServerTest implementation
|
||||
|
||||
ServerTest::ServerTest(const QString &_host, int _port, const QString &_proto, const QString &_realm, const QString &_str) :
|
||||
host(_host),
|
||||
proto(_proto),
|
||||
realm(_realm),
|
||||
str(_str),
|
||||
port(_port)
|
||||
ServerTest::ServerTest(const QString &_host,
|
||||
int _port,
|
||||
const QString &_proto,
|
||||
const QString &_realm,
|
||||
const QString &_str)
|
||||
: host(_host)
|
||||
, proto(_proto)
|
||||
, realm(_realm)
|
||||
, str(_str)
|
||||
, port(_port)
|
||||
{
|
||||
tcpServer = new QTcpServer(this);
|
||||
connect(tcpServer, SIGNAL(newConnection()), SLOT(server_newConnection()));
|
||||
tcpServer = new QTcpServer(this);
|
||||
connect(tcpServer, &QTcpServer::newConnection, this, &ServerTest::server_newConnection);
|
||||
}
|
||||
|
||||
int ServerTest::reserveId()
|
||||
{
|
||||
int n = 0;
|
||||
while(ids.contains(n))
|
||||
++n;
|
||||
ids += n;
|
||||
return n;
|
||||
int n = 0;
|
||||
while (ids.contains(n))
|
||||
++n;
|
||||
ids += n;
|
||||
return n;
|
||||
}
|
||||
|
||||
void ServerTest::releaseId(int id)
|
||||
{
|
||||
ids.removeAll(id);
|
||||
ids.removeAll(id);
|
||||
}
|
||||
|
||||
void ServerTest::start()
|
||||
{
|
||||
if(!tcpServer->listen(QHostAddress::Any, port))
|
||||
{
|
||||
printf("Error: unable to bind to port %d.\n", port);
|
||||
emit quit();
|
||||
return;
|
||||
}
|
||||
if (!tcpServer->listen(QHostAddress::Any, port)) {
|
||||
printf("Error: unable to bind to port %d.\n", port);
|
||||
emit quit();
|
||||
return;
|
||||
}
|
||||
|
||||
printf("Serving on %s:%d, for protocol %s ...\n", qPrintable(host), port, qPrintable(proto));
|
||||
printf("Serving on %s:%d, for protocol %s ...\n", qPrintable(host), port, qPrintable(proto));
|
||||
}
|
||||
|
||||
void ServerTest::server_newConnection()
|
||||
{
|
||||
QTcpSocket *sock = tcpServer->nextPendingConnection();
|
||||
new ServerTestHandler(this, sock, host, proto, realm, str);
|
||||
QTcpSocket *sock = tcpServer->nextPendingConnection();
|
||||
new ServerTestHandler(this, sock, host, proto, realm, str);
|
||||
}
|
||||
|
||||
// ---
|
||||
|
||||
void usage()
|
||||
{
|
||||
printf("usage: saslserver host (message)\n");
|
||||
printf("options: --proto=x, --realm=x\n");
|
||||
printf("usage: saslserver host (message)\n");
|
||||
printf("options: --proto=x, --realm=x\n");
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
QCA::Initializer init;
|
||||
QCoreApplication qapp(argc, argv);
|
||||
QCA::Initializer init;
|
||||
QCoreApplication qapp(argc, argv);
|
||||
|
||||
QCA::setAppName("saslserver");
|
||||
QCA::setAppName(QStringLiteral("saslserver"));
|
||||
|
||||
QStringList args = qapp.arguments();
|
||||
args.removeFirst();
|
||||
QStringList args = qapp.arguments();
|
||||
args.removeFirst();
|
||||
|
||||
// options
|
||||
QString proto = "qcatest"; // default protocol
|
||||
QString realm;
|
||||
for(int n = 0; n < args.count(); ++n)
|
||||
{
|
||||
if(!args[n].startsWith("--"))
|
||||
continue;
|
||||
// options
|
||||
QString proto = QStringLiteral("qcatest"); // default protocol
|
||||
QString realm;
|
||||
for (int n = 0; n < args.count(); ++n) {
|
||||
if (!args[n].startsWith(QLatin1String("--")))
|
||||
continue;
|
||||
|
||||
QString opt = args[n].mid(2);
|
||||
QString var, val;
|
||||
int at = opt.indexOf('=');
|
||||
if(at != -1)
|
||||
{
|
||||
var = opt.mid(0, at);
|
||||
val = opt.mid(at + 1);
|
||||
}
|
||||
else
|
||||
var = opt;
|
||||
QString opt = args[n].mid(2);
|
||||
QString var, val;
|
||||
int at = opt.indexOf(QLatin1Char('='));
|
||||
if (at != -1) {
|
||||
var = opt.mid(0, at);
|
||||
val = opt.mid(at + 1);
|
||||
} else
|
||||
var = opt;
|
||||
|
||||
if(var == "proto")
|
||||
proto = val;
|
||||
else if(var == "realm")
|
||||
realm = val;
|
||||
if (var == QLatin1String("proto"))
|
||||
proto = val;
|
||||
else if (var == QLatin1String("realm"))
|
||||
realm = val;
|
||||
|
||||
args.removeAt(n);
|
||||
--n; // adjust position
|
||||
}
|
||||
args.removeAt(n);
|
||||
--n; // adjust position
|
||||
}
|
||||
|
||||
if(args.count() < 1)
|
||||
{
|
||||
usage();
|
||||
return 0;
|
||||
}
|
||||
if (args.count() < 1) {
|
||||
usage();
|
||||
return 0;
|
||||
}
|
||||
|
||||
QString host;
|
||||
int port = 8001; // default port
|
||||
QString host;
|
||||
int port = 8001; // default port
|
||||
|
||||
QString hostinput = args[0];
|
||||
QString str = "Hello, World";
|
||||
if(args.count() >= 2)
|
||||
str = args[1];
|
||||
QString hostinput = args[0];
|
||||
QString str = QStringLiteral("Hello, World");
|
||||
if (args.count() >= 2)
|
||||
str = args[1];
|
||||
|
||||
int at = hostinput.indexOf(':');
|
||||
if(at != -1)
|
||||
{
|
||||
host = hostinput.mid(0, at);
|
||||
port = hostinput.mid(at + 1).toInt();
|
||||
}
|
||||
else
|
||||
host = hostinput;
|
||||
int at = hostinput.indexOf(QLatin1Char(':'));
|
||||
if (at != -1) {
|
||||
host = hostinput.mid(0, at);
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 2)
|
||||
port = QStringView(hostinput).mid(at + 1).toInt();
|
||||
#else
|
||||
port = hostinput.midRef(at + 1).toInt();
|
||||
#endif
|
||||
} else
|
||||
host = hostinput;
|
||||
|
||||
if(!QCA::isSupported("sasl"))
|
||||
{
|
||||
printf("Error: SASL support not found.\n");
|
||||
return 1;
|
||||
}
|
||||
if (!QCA::isSupported("sasl")) {
|
||||
printf("Error: SASL support not found.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
ServerTest server(host, port, proto, realm, str);
|
||||
QObject::connect(&server, SIGNAL(quit()), &qapp, SLOT(quit()));
|
||||
QTimer::singleShot(0, &server, SLOT(start()));
|
||||
qapp.exec();
|
||||
ServerTest server(host, port, proto, realm, str);
|
||||
QObject::connect(&server, &ServerTest::quit, &qapp, &QCoreApplication::quit);
|
||||
QTimer::singleShot(0, &server, &ServerTest::start);
|
||||
qapp.exec();
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include "saslserver.moc"
|
||||
|
@ -1,8 +1,10 @@
|
||||
set(sslservtest_bin_SRCS sslservtest.cpp)
|
||||
|
||||
MY_AUTOMOC( sslservtest_bin_SRCS )
|
||||
|
||||
add_executable(sslservtest ${sslservtest_bin_SRCS})
|
||||
|
||||
target_link_qca_libraries(sslservtest)
|
||||
target_link_libraries(sslservtest ${QT_QTNETWORK_LIBRARY})
|
||||
if(QT6)
|
||||
target_link_libraries(sslservtest Qt6::Network)
|
||||
else()
|
||||
target_link_libraries(sslservtest Qt5::Network)
|
||||
endif()
|
||||
|
@ -34,218 +34,227 @@
|
||||
#endif
|
||||
|
||||
char pemdata_cert[] =
|
||||
"-----BEGIN CERTIFICATE-----\n"
|
||||
"MIICeTCCAeKgAwIBAgIRAKKKnOj6Aarmwf0phApitVAwDQYJKoZIhvcNAQEFBQAw\n"
|
||||
"ODELMAkGA1UEBhMCVVMxFDASBgNVBAoTC0V4YW1wbGUgT3JnMRMwEQYDVQQDEwpF\n"
|
||||
"eGFtcGxlIENBMB4XDTA2MDMxNTA3MDU1MloXDTA3MDMxNTA3MDU1MlowOjEVMBMG\n"
|
||||
"A1UEAxMMRXhhbXBsZSBVc2VyMQswCQYDVQQGEwJVUzEUMBIGA1UEChMLRXhhbXBs\n"
|
||||
"ZSBPcmcwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAPkKn0FfHMvRZv+3uFcw\n"
|
||||
"VrOadJmANzLVeVW/DHZp4CXokXSksM66ZMqFuQRBk5rnIZZpZmVp1tTRDVt9sEAY\n"
|
||||
"YNa8CRM4HXkVlU0lCKdey18CSq2VuSvNtw8dDpoBmQt3nr9tePvKHnpS3nm6YjR2\n"
|
||||
"NEvIKt1P4mHzYXLmwoF24C1bAgMBAAGjgYAwfjAdBgNVHQ4EFgQUmQIdzyDaPYWF\n"
|
||||
"fPJ8PPOOm1eSsucwHwYDVR0jBBgwFoAUkCglAizTO7iqwLeaO6r/8kJuqhMwDAYD\n"
|
||||
"VR0TAQH/BAIwADAeBgNVHREEFzAVgRNleGFtcGxlQGV4YW1wbGUuY29tMA4GA1Ud\n"
|
||||
"DwEB/wQEAwIF4DANBgkqhkiG9w0BAQUFAAOBgQAuhbiUgy2a++EUccaonID7eTJZ\n"
|
||||
"F3D5qXMqUpQxlYxU8du+9AxDD7nFxTMkQC2pzfmEc1znRNmJ1ZeLRL72VYsVndcT\n"
|
||||
"psyM8ABkvPp1d2jWIyccVjGpt+/RN5IPKm/YIbtIZcywvWuXrOp1lanVmppLfPnO\n"
|
||||
"6yneBkC9iqjOv/+Q+A==\n"
|
||||
"-----END CERTIFICATE-----\n";
|
||||
"-----BEGIN CERTIFICATE-----\n"
|
||||
"MIICeTCCAeKgAwIBAgIRAKKKnOj6Aarmwf0phApitVAwDQYJKoZIhvcNAQEFBQAw\n"
|
||||
"ODELMAkGA1UEBhMCVVMxFDASBgNVBAoTC0V4YW1wbGUgT3JnMRMwEQYDVQQDEwpF\n"
|
||||
"eGFtcGxlIENBMB4XDTA2MDMxNTA3MDU1MloXDTA3MDMxNTA3MDU1MlowOjEVMBMG\n"
|
||||
"A1UEAxMMRXhhbXBsZSBVc2VyMQswCQYDVQQGEwJVUzEUMBIGA1UEChMLRXhhbXBs\n"
|
||||
"ZSBPcmcwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAPkKn0FfHMvRZv+3uFcw\n"
|
||||
"VrOadJmANzLVeVW/DHZp4CXokXSksM66ZMqFuQRBk5rnIZZpZmVp1tTRDVt9sEAY\n"
|
||||
"YNa8CRM4HXkVlU0lCKdey18CSq2VuSvNtw8dDpoBmQt3nr9tePvKHnpS3nm6YjR2\n"
|
||||
"NEvIKt1P4mHzYXLmwoF24C1bAgMBAAGjgYAwfjAdBgNVHQ4EFgQUmQIdzyDaPYWF\n"
|
||||
"fPJ8PPOOm1eSsucwHwYDVR0jBBgwFoAUkCglAizTO7iqwLeaO6r/8kJuqhMwDAYD\n"
|
||||
"VR0TAQH/BAIwADAeBgNVHREEFzAVgRNleGFtcGxlQGV4YW1wbGUuY29tMA4GA1Ud\n"
|
||||
"DwEB/wQEAwIF4DANBgkqhkiG9w0BAQUFAAOBgQAuhbiUgy2a++EUccaonID7eTJZ\n"
|
||||
"F3D5qXMqUpQxlYxU8du+9AxDD7nFxTMkQC2pzfmEc1znRNmJ1ZeLRL72VYsVndcT\n"
|
||||
"psyM8ABkvPp1d2jWIyccVjGpt+/RN5IPKm/YIbtIZcywvWuXrOp1lanVmppLfPnO\n"
|
||||
"6yneBkC9iqjOv/+Q+A==\n"
|
||||
"-----END CERTIFICATE-----\n";
|
||||
|
||||
char pemdata_privkey[] =
|
||||
"-----BEGIN PRIVATE KEY-----\n"
|
||||
"MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAPkKn0FfHMvRZv+3\n"
|
||||
"uFcwVrOadJmANzLVeVW/DHZp4CXokXSksM66ZMqFuQRBk5rnIZZpZmVp1tTRDVt9\n"
|
||||
"sEAYYNa8CRM4HXkVlU0lCKdey18CSq2VuSvNtw8dDpoBmQt3nr9tePvKHnpS3nm6\n"
|
||||
"YjR2NEvIKt1P4mHzYXLmwoF24C1bAgMBAAECgYEAyIjJHDaeVXDU42zovyxpZE4n\n"
|
||||
"PcOEryY+gdFJE8DFgUD4f1huFsj4iCuNg+PaG42p+hf9IARNvSho/RcEaVg4AJrV\n"
|
||||
"jRP8r7fSqcIGr6lGuvDFFv3SU5ddy84g5oqLYGKvuPSHMGfVsZSxAwOrzD4bH19L\n"
|
||||
"SNqtNcpdBsBd7ZiEE4ECQQD/oJGui9D5Dx3QVcS+QV4F8wuyN9jYIANmX/17o0fl\n"
|
||||
"BL0bwRU4RICwadrcybi5N0JQLIYSUm2HGqNvAJbtnuQxAkEA+WeYLLYPeawcy+WU\n"
|
||||
"kGcOR7BUjHiG71+6cvU4XIDW2bezA04fqWXkZRFAwHTMpQb785/XalFftgS21kql\n"
|
||||
"8yLDSwJAHkeT2hwftdDPlEUEmBDAJW5DvWmWGwu3u2G1cfbGZl9oUyhM7ixXHg57\n"
|
||||
"6VlPs0jTZxHPE86FwNIr99MXDbCbkQJBAMDFOJK+ecGirXNP1P+0GA6DFSap9inJ\n"
|
||||
"BRTbwx+EmgwX966DUOefEOSpbDIVVSPs/Qr2LgtIMEFA7Y0+j3wZD3cCQBsTwccd\n"
|
||||
"ASQx59xakpq11eOlTYz14rjwodr4QMyj26WxEPJtz7hKokx/+EH6fWuPIUSrROM5\n"
|
||||
"07y2gaVbYxtis0s=\n"
|
||||
"-----END PRIVATE KEY-----\n";
|
||||
"-----BEGIN PRIVATE KEY-----\n"
|
||||
"MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAPkKn0FfHMvRZv+3\n"
|
||||
"uFcwVrOadJmANzLVeVW/DHZp4CXokXSksM66ZMqFuQRBk5rnIZZpZmVp1tTRDVt9\n"
|
||||
"sEAYYNa8CRM4HXkVlU0lCKdey18CSq2VuSvNtw8dDpoBmQt3nr9tePvKHnpS3nm6\n"
|
||||
"YjR2NEvIKt1P4mHzYXLmwoF24C1bAgMBAAECgYEAyIjJHDaeVXDU42zovyxpZE4n\n"
|
||||
"PcOEryY+gdFJE8DFgUD4f1huFsj4iCuNg+PaG42p+hf9IARNvSho/RcEaVg4AJrV\n"
|
||||
"jRP8r7fSqcIGr6lGuvDFFv3SU5ddy84g5oqLYGKvuPSHMGfVsZSxAwOrzD4bH19L\n"
|
||||
"SNqtNcpdBsBd7ZiEE4ECQQD/oJGui9D5Dx3QVcS+QV4F8wuyN9jYIANmX/17o0fl\n"
|
||||
"BL0bwRU4RICwadrcybi5N0JQLIYSUm2HGqNvAJbtnuQxAkEA+WeYLLYPeawcy+WU\n"
|
||||
"kGcOR7BUjHiG71+6cvU4XIDW2bezA04fqWXkZRFAwHTMpQb785/XalFftgS21kql\n"
|
||||
"8yLDSwJAHkeT2hwftdDPlEUEmBDAJW5DvWmWGwu3u2G1cfbGZl9oUyhM7ixXHg57\n"
|
||||
"6VlPs0jTZxHPE86FwNIr99MXDbCbkQJBAMDFOJK+ecGirXNP1P+0GA6DFSap9inJ\n"
|
||||
"BRTbwx+EmgwX966DUOefEOSpbDIVVSPs/Qr2LgtIMEFA7Y0+j3wZD3cCQBsTwccd\n"
|
||||
"ASQx59xakpq11eOlTYz14rjwodr4QMyj26WxEPJtz7hKokx/+EH6fWuPIUSrROM5\n"
|
||||
"07y2gaVbYxtis0s=\n"
|
||||
"-----END PRIVATE KEY-----\n";
|
||||
|
||||
class SecureServer : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum { Idle, Handshaking, Active, Closing };
|
||||
|
||||
SecureServer(quint16 _port) : port(_port)
|
||||
enum
|
||||
{
|
||||
server = new QTcpServer;
|
||||
connect( server, SIGNAL(newConnection()), SLOT(server_handleConnection()) );
|
||||
Idle,
|
||||
Handshaking,
|
||||
Active,
|
||||
Closing
|
||||
};
|
||||
|
||||
ssl = new QCA::TLS;
|
||||
connect(ssl, SIGNAL(handshaken()), SLOT(ssl_handshaken()));
|
||||
connect(ssl, SIGNAL(readyRead()), SLOT(ssl_readyRead()));
|
||||
connect(ssl, SIGNAL(readyReadOutgoing()), SLOT(ssl_readyReadOutgoing()));
|
||||
connect(ssl, SIGNAL(closed()), SLOT(ssl_closed()));
|
||||
connect(ssl, SIGNAL(error()), SLOT(ssl_error()));
|
||||
SecureServer(quint16 _port)
|
||||
: port(_port)
|
||||
{
|
||||
server = new QTcpServer;
|
||||
connect(server, &QTcpServer::newConnection, this, &SecureServer::server_handleConnection);
|
||||
|
||||
cert = QCA::Certificate::fromPEM(pemdata_cert);
|
||||
privkey = QCA::PrivateKey::fromPEM(pemdata_privkey);
|
||||
ssl = new QCA::TLS;
|
||||
connect(ssl, &QCA::TLS::handshaken, this, &SecureServer::ssl_handshaken);
|
||||
connect(ssl, &QCA::TLS::readyRead, this, &SecureServer::ssl_readyRead);
|
||||
connect(ssl, &QCA::TLS::readyReadOutgoing, this, &SecureServer::ssl_readyReadOutgoing);
|
||||
connect(ssl, &QCA::TLS::closed, this, &SecureServer::ssl_closed);
|
||||
connect(ssl, &QCA::TLS::error, this, &SecureServer::ssl_error);
|
||||
|
||||
mode = Idle;
|
||||
cert = QCA::Certificate::fromPEM(QString::fromLatin1(pemdata_cert));
|
||||
privkey = QCA::PrivateKey::fromPEM(QString::fromLatin1(pemdata_privkey));
|
||||
|
||||
mode = Idle;
|
||||
}
|
||||
|
||||
~SecureServer()
|
||||
~SecureServer() override
|
||||
{
|
||||
delete ssl;
|
||||
delete server;
|
||||
delete ssl;
|
||||
delete server;
|
||||
}
|
||||
|
||||
void start()
|
||||
{
|
||||
if(cert.isNull()) {
|
||||
qDebug() << "Error loading cert!";
|
||||
QTimer::singleShot(0, this, SIGNAL(quit()));
|
||||
return;
|
||||
}
|
||||
if(privkey.isNull()) {
|
||||
qDebug() << "Error loading private key!";
|
||||
QTimer::singleShot(0, this, SIGNAL(quit()));
|
||||
return;
|
||||
}
|
||||
if(false == server->listen(QHostAddress::Any, port)) {
|
||||
qDebug() << "Error binding to port " << port;
|
||||
QTimer::singleShot(0, this, SIGNAL(quit()));
|
||||
return;
|
||||
}
|
||||
qDebug() << "Listening on port" << port;
|
||||
if (cert.isNull()) {
|
||||
qDebug() << "Error loading cert!";
|
||||
QTimer::singleShot(0, this, &SecureServer::quit);
|
||||
return;
|
||||
}
|
||||
if (privkey.isNull()) {
|
||||
qDebug() << "Error loading private key!";
|
||||
QTimer::singleShot(0, this, &SecureServer::quit);
|
||||
return;
|
||||
}
|
||||
if (false == server->listen(QHostAddress::Any, port)) {
|
||||
qDebug() << "Error binding to port " << port;
|
||||
QTimer::singleShot(0, this, &SecureServer::quit);
|
||||
return;
|
||||
}
|
||||
qDebug() << "Listening on port" << port;
|
||||
}
|
||||
|
||||
signals:
|
||||
Q_SIGNALS:
|
||||
void quit();
|
||||
|
||||
private slots:
|
||||
private Q_SLOTS:
|
||||
void sock_readyRead()
|
||||
{
|
||||
QByteArray buf(sock->bytesAvailable(), 0x00);
|
||||
QByteArray buf(sock->bytesAvailable(), 0x00);
|
||||
|
||||
int num = sock->read(buf.data(), buf.size());
|
||||
int num = sock->read(buf.data(), buf.size());
|
||||
|
||||
if ( -1 == num )
|
||||
qDebug() << "Error reading data from socket";
|
||||
if (-1 == num)
|
||||
qDebug() << "Error reading data from socket";
|
||||
|
||||
if (num < buf.size() )
|
||||
buf.resize(num);
|
||||
if (num < buf.size())
|
||||
buf.resize(num);
|
||||
|
||||
ssl->writeIncoming(buf);
|
||||
ssl->writeIncoming(buf);
|
||||
}
|
||||
|
||||
void server_handleConnection()
|
||||
{
|
||||
// Note: only 1 connection supported at a time in this example!
|
||||
if(mode != Idle) {
|
||||
QTcpSocket* tmp = server->nextPendingConnection();
|
||||
tmp->close();
|
||||
connect(tmp, SIGNAL(disconnected()), tmp, SLOT(deleteLater()));
|
||||
qDebug() << "throwing away extra connection";
|
||||
return;
|
||||
}
|
||||
mode = Handshaking;
|
||||
sock = server->nextPendingConnection();
|
||||
connect(sock, SIGNAL(readyRead()), SLOT(sock_readyRead()));
|
||||
connect(sock, SIGNAL(disconnected()), SLOT(sock_disconnected()));
|
||||
connect(sock, SIGNAL(error(QAbstractSocket::SocketError)),
|
||||
SLOT(sock_error(QAbstractSocket::SocketError)));
|
||||
connect(sock, SIGNAL(bytesWritten(qint64)), SLOT(sock_bytesWritten(qint64)));
|
||||
// Note: only 1 connection supported at a time in this example!
|
||||
if (mode != Idle) {
|
||||
QTcpSocket *tmp = server->nextPendingConnection();
|
||||
tmp->close();
|
||||
connect(tmp, &QTcpSocket::disconnected, tmp, &QTcpSocket::deleteLater);
|
||||
qDebug() << "throwing away extra connection";
|
||||
return;
|
||||
}
|
||||
mode = Handshaking;
|
||||
sock = server->nextPendingConnection();
|
||||
connect(sock, &QTcpSocket::readyRead, this, &SecureServer::sock_readyRead);
|
||||
connect(sock, &QTcpSocket::disconnected, this, &SecureServer::sock_disconnected);
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
|
||||
connect(sock, &QTcpSocket::errorOccurred, this, &SecureServer::sock_error);
|
||||
#else
|
||||
connect(sock, QOverload<QAbstractSocket::SocketError>::of(&QTcpSocket::error), this, &SecureServer::sock_error);
|
||||
#endif
|
||||
connect(sock, &QTcpSocket::bytesWritten, this, &SecureServer::sock_bytesWritten);
|
||||
|
||||
qDebug() << "Connection received! Starting TLS handshake.";
|
||||
ssl->setCertificate(cert, privkey);
|
||||
ssl->startServer();
|
||||
qDebug() << "Connection received! Starting TLS handshake.";
|
||||
ssl->setCertificate(cert, privkey);
|
||||
ssl->startServer();
|
||||
}
|
||||
|
||||
void sock_disconnected()
|
||||
{
|
||||
qDebug() << "Connection closed.";
|
||||
qDebug() << "Connection closed.";
|
||||
}
|
||||
|
||||
void sock_bytesWritten(qint64 x)
|
||||
{
|
||||
if(mode == Active && sent) {
|
||||
qint64 bytes = ssl->convertBytesWritten(x);
|
||||
bytesLeft -= bytes;
|
||||
if (mode == Active && sent) {
|
||||
qint64 bytes = ssl->convertBytesWritten(x);
|
||||
bytesLeft -= bytes;
|
||||
|
||||
if(bytesLeft == 0) {
|
||||
mode = Closing;
|
||||
qDebug() << "Data transfer complete - SSL shutting down";
|
||||
ssl->close();
|
||||
}
|
||||
}
|
||||
if (bytesLeft == 0) {
|
||||
mode = Closing;
|
||||
qDebug() << "Data transfer complete - SSL shutting down";
|
||||
ssl->close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sock_error(QAbstractSocket::SocketError error)
|
||||
{
|
||||
qDebug() << "Socket error: " << (unsigned) error;
|
||||
qDebug() << "Socket error: " << (unsigned)error;
|
||||
}
|
||||
|
||||
void ssl_handshaken()
|
||||
{
|
||||
qDebug() << "Successful SSL handshake. Waiting for newline.";
|
||||
bytesLeft = 0;
|
||||
sent = false;
|
||||
mode = Active;
|
||||
ssl->continueAfterStep();
|
||||
qDebug() << "Successful SSL handshake. Waiting for newline.";
|
||||
bytesLeft = 0;
|
||||
sent = false;
|
||||
mode = Active;
|
||||
ssl->continueAfterStep();
|
||||
}
|
||||
|
||||
void ssl_readyRead()
|
||||
{
|
||||
QByteArray a = ssl->read();
|
||||
QByteArray b =
|
||||
"<html>\n"
|
||||
"<head><title>Test</title></head>\n"
|
||||
"<body>this is only a test</body>\n"
|
||||
"</html>\n";
|
||||
ssl->read();
|
||||
QByteArray b =
|
||||
"<html>\n"
|
||||
"<head><title>Test</title></head>\n"
|
||||
"<body>this is only a test</body>\n"
|
||||
"</html>\n";
|
||||
|
||||
qDebug() << "Sending test response.";
|
||||
sent = true;
|
||||
ssl->write(b);
|
||||
qDebug() << "Sending test response.";
|
||||
sent = true;
|
||||
ssl->write(b);
|
||||
}
|
||||
|
||||
void ssl_readyReadOutgoing()
|
||||
{
|
||||
int plainBytes;
|
||||
QByteArray outgoingData = ssl->readOutgoing(&plainBytes);
|
||||
sock->write( outgoingData );
|
||||
int plainBytes;
|
||||
QByteArray outgoingData = ssl->readOutgoing(&plainBytes);
|
||||
sock->write(outgoingData);
|
||||
}
|
||||
|
||||
void ssl_closed()
|
||||
{
|
||||
qDebug() << "Closing socket.";
|
||||
sock->close();
|
||||
mode = Idle;
|
||||
qDebug() << "Closing socket.";
|
||||
sock->close();
|
||||
mode = Idle;
|
||||
}
|
||||
|
||||
void ssl_error()
|
||||
{
|
||||
if(ssl->errorCode() == QCA::TLS::ErrorHandshake) {
|
||||
qDebug() << "SSL Handshake Error! Closing.";
|
||||
sock->close();
|
||||
}
|
||||
else {
|
||||
qDebug() << "SSL Error! Closing.";
|
||||
sock->close();
|
||||
}
|
||||
mode = Idle;
|
||||
if (ssl->errorCode() == QCA::TLS::ErrorHandshake) {
|
||||
qDebug() << "SSL Handshake Error! Closing.";
|
||||
sock->close();
|
||||
} else {
|
||||
qDebug() << "SSL Error! Closing.";
|
||||
sock->close();
|
||||
}
|
||||
mode = Idle;
|
||||
}
|
||||
|
||||
private:
|
||||
quint16 port;
|
||||
QTcpServer *server;
|
||||
QTcpSocket *sock;
|
||||
QCA::TLS *ssl;
|
||||
quint16 port;
|
||||
QTcpServer * server;
|
||||
QTcpSocket * sock;
|
||||
QCA::TLS * ssl;
|
||||
QCA::Certificate cert;
|
||||
QCA::PrivateKey privkey;
|
||||
QCA::PrivateKey privkey;
|
||||
|
||||
bool sent;
|
||||
int mode;
|
||||
bool sent;
|
||||
int mode;
|
||||
qint64 bytesLeft;
|
||||
};
|
||||
|
||||
@ -256,15 +265,15 @@ int main(int argc, char **argv)
|
||||
QCA::Initializer init;
|
||||
|
||||
QCoreApplication app(argc, argv);
|
||||
int port = argc > 1 ? QString(argv[1]).toInt() : 8000;
|
||||
int port = argc > 1 ? QString::fromLatin1(argv[1]).toInt() : 8000;
|
||||
|
||||
if(!QCA::isSupported("tls")) {
|
||||
qDebug() << "TLS not supported!";
|
||||
return 1;
|
||||
if (!QCA::isSupported("tls")) {
|
||||
qDebug() << "TLS not supported!";
|
||||
return 1;
|
||||
}
|
||||
|
||||
SecureServer *server = new SecureServer(port);
|
||||
QObject::connect(server, SIGNAL(quit()), &app, SLOT(quit()));
|
||||
QObject::connect(server, &SecureServer::quit, &app, &QCoreApplication::quit);
|
||||
server->start();
|
||||
app.exec();
|
||||
delete server;
|
||||
|
@ -1,8 +1,10 @@
|
||||
set(ssltest_bin_SRCS ssltest.cpp)
|
||||
|
||||
MY_AUTOMOC( ssltest_bin_SRCS)
|
||||
|
||||
add_executable(ssltest ${ssltest_bin_SRCS})
|
||||
|
||||
target_link_qca_libraries(ssltest)
|
||||
target_link_libraries(ssltest ${QT_QTNETWORK_LIBRARY})
|
||||
if(QT6)
|
||||
target_link_libraries(ssltest Qt6::Network)
|
||||
else()
|
||||
target_link_libraries(ssltest Qt5::Network)
|
||||
endif()
|
||||
|
@ -29,308 +29,303 @@
|
||||
#endif
|
||||
|
||||
char exampleCA_cert[] =
|
||||
"-----BEGIN CERTIFICATE-----\n"
|
||||
"MIICSzCCAbSgAwIBAgIBADANBgkqhkiG9w0BAQUFADA4MRMwEQYDVQQDEwpFeGFt\n"
|
||||
"cGxlIENBMQswCQYDVQQGEwJVUzEUMBIGA1UEChMLRXhhbXBsZSBPcmcwHhcNMDYw\n"
|
||||
"MzE1MDY1ODMyWhcNMDYwNDE1MDY1ODMyWjA4MRMwEQYDVQQDEwpFeGFtcGxlIENB\n"
|
||||
"MQswCQYDVQQGEwJVUzEUMBIGA1UEChMLRXhhbXBsZSBPcmcwgZ8wDQYJKoZIhvcN\n"
|
||||
"AQEBBQADgY0AMIGJAoGBAL6ULdOxmpeZ+G/ypV12eNO4qnHSVIPTrYPkQuweXqPy\n"
|
||||
"atwGFheG+hLVsNIh9GGOS0tCe7a3hBBKN0BJg1ppfk2x39cDx7hefYqjBuZvp/0O\n"
|
||||
"8Ja3qlQiJLezITZKLxMBrsibcvcuH8zpfUdys2yaN+YGeqNfjQuoNN3Byl1TwuGJ\n"
|
||||
"AgMBAAGjZTBjMB0GA1UdDgQWBBSQKCUCLNM7uKrAt5o7qv/yQm6qEzASBgNVHRMB\n"
|
||||
"Af8ECDAGAQEBAgEIMB4GA1UdEQQXMBWBE2V4YW1wbGVAZXhhbXBsZS5jb20wDgYD\n"
|
||||
"VR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBBQUAA4GBAAh+SIeT1Ao5qInw8oMSoTdO\n"
|
||||
"lQ6h67ec/Jk5KmK4OoskuimmHI0Sp0C5kOCLehXbsVWW8pXsNC2fv0d2HkdaSUcX\n"
|
||||
"hwLzqgyZXd4mupIYlaOTZhuHDwWPCAOZS4LVsi2tndTRHKCP12441JjNKhmZRhkR\n"
|
||||
"u5zzD60nWgM9dKTaxuZM\n"
|
||||
"-----END CERTIFICATE-----\n";
|
||||
"-----BEGIN CERTIFICATE-----\n"
|
||||
"MIICSzCCAbSgAwIBAgIBADANBgkqhkiG9w0BAQUFADA4MRMwEQYDVQQDEwpFeGFt\n"
|
||||
"cGxlIENBMQswCQYDVQQGEwJVUzEUMBIGA1UEChMLRXhhbXBsZSBPcmcwHhcNMDYw\n"
|
||||
"MzE1MDY1ODMyWhcNMDYwNDE1MDY1ODMyWjA4MRMwEQYDVQQDEwpFeGFtcGxlIENB\n"
|
||||
"MQswCQYDVQQGEwJVUzEUMBIGA1UEChMLRXhhbXBsZSBPcmcwgZ8wDQYJKoZIhvcN\n"
|
||||
"AQEBBQADgY0AMIGJAoGBAL6ULdOxmpeZ+G/ypV12eNO4qnHSVIPTrYPkQuweXqPy\n"
|
||||
"atwGFheG+hLVsNIh9GGOS0tCe7a3hBBKN0BJg1ppfk2x39cDx7hefYqjBuZvp/0O\n"
|
||||
"8Ja3qlQiJLezITZKLxMBrsibcvcuH8zpfUdys2yaN+YGeqNfjQuoNN3Byl1TwuGJ\n"
|
||||
"AgMBAAGjZTBjMB0GA1UdDgQWBBSQKCUCLNM7uKrAt5o7qv/yQm6qEzASBgNVHRMB\n"
|
||||
"Af8ECDAGAQEBAgEIMB4GA1UdEQQXMBWBE2V4YW1wbGVAZXhhbXBsZS5jb20wDgYD\n"
|
||||
"VR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBBQUAA4GBAAh+SIeT1Ao5qInw8oMSoTdO\n"
|
||||
"lQ6h67ec/Jk5KmK4OoskuimmHI0Sp0C5kOCLehXbsVWW8pXsNC2fv0d2HkdaSUcX\n"
|
||||
"hwLzqgyZXd4mupIYlaOTZhuHDwWPCAOZS4LVsi2tndTRHKCP12441JjNKhmZRhkR\n"
|
||||
"u5zzD60nWgM9dKTaxuZM\n"
|
||||
"-----END CERTIFICATE-----\n";
|
||||
|
||||
void showCertInfo(const QCA::Certificate &cert)
|
||||
{
|
||||
printf("-- Cert --\n");
|
||||
printf(" CN: %s\n", qPrintable(cert.commonName()));
|
||||
printf(" Valid from: %s, until %s\n",
|
||||
qPrintable(cert.notValidBefore().toString()),
|
||||
qPrintable(cert.notValidAfter().toString()));
|
||||
printf(" PEM:\n%s\n", qPrintable(cert.toPEM()));
|
||||
printf("-- Cert --\n");
|
||||
printf(" CN: %s\n", qPrintable(cert.commonName()));
|
||||
printf(" Valid from: %s, until %s\n",
|
||||
qPrintable(cert.notValidBefore().toString()),
|
||||
qPrintable(cert.notValidAfter().toString()));
|
||||
printf(" PEM:\n%s\n", qPrintable(cert.toPEM()));
|
||||
}
|
||||
|
||||
static QString validityToString(QCA::Validity v)
|
||||
{
|
||||
QString s;
|
||||
switch(v)
|
||||
{
|
||||
case QCA::ValidityGood:
|
||||
s = "Validated";
|
||||
break;
|
||||
case QCA::ErrorRejected:
|
||||
s = "Root CA is marked to reject the specified purpose";
|
||||
break;
|
||||
case QCA::ErrorUntrusted:
|
||||
s = "Certificate not trusted for the required purpose";
|
||||
break;
|
||||
case QCA::ErrorSignatureFailed:
|
||||
s = "Invalid signature";
|
||||
break;
|
||||
case QCA::ErrorInvalidCA:
|
||||
s = "Invalid CA certificate";
|
||||
break;
|
||||
case QCA::ErrorInvalidPurpose:
|
||||
s = "Invalid certificate purpose";
|
||||
break;
|
||||
case QCA::ErrorSelfSigned:
|
||||
s = "Certificate is self-signed";
|
||||
break;
|
||||
case QCA::ErrorRevoked:
|
||||
s = "Certificate has been revoked";
|
||||
break;
|
||||
case QCA::ErrorPathLengthExceeded:
|
||||
s = "Maximum certificate chain length exceeded";
|
||||
break;
|
||||
case QCA::ErrorExpired:
|
||||
s = "Certificate has expired";
|
||||
break;
|
||||
case QCA::ErrorExpiredCA:
|
||||
s = "CA has expired";
|
||||
break;
|
||||
case QCA::ErrorValidityUnknown:
|
||||
default:
|
||||
s = "General certificate validation error";
|
||||
break;
|
||||
}
|
||||
return s;
|
||||
QString s;
|
||||
switch (v) {
|
||||
case QCA::ValidityGood:
|
||||
s = QStringLiteral("Validated");
|
||||
break;
|
||||
case QCA::ErrorRejected:
|
||||
s = QStringLiteral("Root CA is marked to reject the specified purpose");
|
||||
break;
|
||||
case QCA::ErrorUntrusted:
|
||||
s = QStringLiteral("Certificate not trusted for the required purpose");
|
||||
break;
|
||||
case QCA::ErrorSignatureFailed:
|
||||
s = QStringLiteral("Invalid signature");
|
||||
break;
|
||||
case QCA::ErrorInvalidCA:
|
||||
s = QStringLiteral("Invalid CA certificate");
|
||||
break;
|
||||
case QCA::ErrorInvalidPurpose:
|
||||
s = QStringLiteral("Invalid certificate purpose");
|
||||
break;
|
||||
case QCA::ErrorSelfSigned:
|
||||
s = QStringLiteral("Certificate is self-signed");
|
||||
break;
|
||||
case QCA::ErrorRevoked:
|
||||
s = QStringLiteral("Certificate has been revoked");
|
||||
break;
|
||||
case QCA::ErrorPathLengthExceeded:
|
||||
s = QStringLiteral("Maximum certificate chain length exceeded");
|
||||
break;
|
||||
case QCA::ErrorExpired:
|
||||
s = QStringLiteral("Certificate has expired");
|
||||
break;
|
||||
case QCA::ErrorExpiredCA:
|
||||
s = QStringLiteral("CA has expired");
|
||||
break;
|
||||
case QCA::ErrorValidityUnknown:
|
||||
default:
|
||||
s = QStringLiteral("General certificate validation error");
|
||||
break;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
class SecureTest : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
public:
|
||||
SecureTest()
|
||||
{
|
||||
sock_done = false;
|
||||
ssl_done = false;
|
||||
SecureTest()
|
||||
{
|
||||
sock_done = false;
|
||||
ssl_done = false;
|
||||
|
||||
sock = new QTcpSocket;
|
||||
connect(sock, SIGNAL(connected()), SLOT(sock_connected()));
|
||||
connect(sock, SIGNAL(readyRead()), SLOT(sock_readyRead()));
|
||||
connect(sock, SIGNAL(error(QAbstractSocket::SocketError)),
|
||||
SLOT(sock_error(QAbstractSocket::SocketError)));
|
||||
sock = new QTcpSocket;
|
||||
connect(sock, &QTcpSocket::connected, this, &SecureTest::sock_connected);
|
||||
connect(sock, &QTcpSocket::readyRead, this, &SecureTest::sock_readyRead);
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
|
||||
connect(sock, &QTcpSocket::errorOccurred, this, &SecureTest::sock_error);
|
||||
#else
|
||||
connect(sock, QOverload<QAbstractSocket::SocketError>::of(&QTcpSocket::error), this, &SecureTest::sock_error);
|
||||
#endif
|
||||
|
||||
ssl = new QCA::TLS;
|
||||
connect(ssl, SIGNAL(certificateRequested()), SLOT(ssl_certificateRequested()));
|
||||
connect(ssl, SIGNAL(handshaken()), SLOT(ssl_handshaken()));
|
||||
connect(ssl, SIGNAL(readyRead()), SLOT(ssl_readyRead()));
|
||||
connect(ssl, SIGNAL(readyReadOutgoing()),
|
||||
SLOT(ssl_readyReadOutgoing()));
|
||||
connect(ssl, SIGNAL(closed()), SLOT(ssl_closed()));
|
||||
connect(ssl, SIGNAL(error()), SLOT(ssl_error()));
|
||||
}
|
||||
ssl = new QCA::TLS;
|
||||
connect(ssl, &QCA::TLS::certificateRequested, this, &SecureTest::ssl_certificateRequested);
|
||||
connect(ssl, &QCA::TLS::handshaken, this, &SecureTest::ssl_handshaken);
|
||||
connect(ssl, &QCA::TLS::readyRead, this, &SecureTest::ssl_readyRead);
|
||||
connect(ssl, &QCA::TLS::readyReadOutgoing, this, &SecureTest::ssl_readyReadOutgoing);
|
||||
connect(ssl, &QCA::TLS::closed, this, &SecureTest::ssl_closed);
|
||||
connect(ssl, &QCA::TLS::error, this, &SecureTest::ssl_error);
|
||||
}
|
||||
|
||||
~SecureTest()
|
||||
{
|
||||
delete ssl;
|
||||
delete sock;
|
||||
}
|
||||
~SecureTest() override
|
||||
{
|
||||
delete ssl;
|
||||
delete sock;
|
||||
}
|
||||
|
||||
void start(const QString &_host)
|
||||
{
|
||||
int n = _host.indexOf(':');
|
||||
int port;
|
||||
if(n != -1)
|
||||
{
|
||||
host = _host.mid(0, n);
|
||||
port = _host.mid(n+1).toInt();
|
||||
}
|
||||
else
|
||||
{
|
||||
host = _host;
|
||||
port = 443;
|
||||
}
|
||||
void start(const QString &_host)
|
||||
{
|
||||
int n = _host.indexOf(QLatin1Char(':'));
|
||||
int port;
|
||||
if (n != -1) {
|
||||
host = _host.mid(0, n);
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
|
||||
port = QStringView(_host).mid(n + 1).toInt();
|
||||
#else
|
||||
port = _host.midRef(n + 1).toInt();
|
||||
#endif
|
||||
} else {
|
||||
host = _host;
|
||||
port = 443;
|
||||
}
|
||||
|
||||
printf("Trying %s:%d...\n", qPrintable(host), port);
|
||||
sock->connectToHost(host, port);
|
||||
}
|
||||
printf("Trying %s:%d...\n", qPrintable(host), port);
|
||||
sock->connectToHost(host, port);
|
||||
}
|
||||
|
||||
signals:
|
||||
void quit();
|
||||
Q_SIGNALS:
|
||||
void quit();
|
||||
|
||||
private slots:
|
||||
void sock_connected()
|
||||
{
|
||||
// We just do this to help doxygen...
|
||||
QCA::TLS *ssl = SecureTest::ssl;
|
||||
private Q_SLOTS:
|
||||
void sock_connected()
|
||||
{
|
||||
// We just do this to help doxygen...
|
||||
QCA::TLS *ssl = SecureTest::ssl;
|
||||
|
||||
printf("Connected, starting TLS handshake...\n");
|
||||
printf("Connected, starting TLS handshake...\n");
|
||||
|
||||
QCA::CertificateCollection rootCerts = QCA::systemStore();
|
||||
QCA::CertificateCollection rootCerts = QCA::systemStore();
|
||||
|
||||
// We add this one to show how, and to make it work with
|
||||
// the server example.
|
||||
rootCerts.addCertificate(QCA::Certificate::fromPEM(exampleCA_cert));
|
||||
// We add this one to show how, and to make it work with
|
||||
// the server example.
|
||||
rootCerts.addCertificate(QCA::Certificate::fromPEM(QString::fromLatin1(exampleCA_cert)));
|
||||
|
||||
if(!QCA::haveSystemStore())
|
||||
printf("Warning: no root certs\n");
|
||||
else
|
||||
ssl->setTrustedCertificates(rootCerts);
|
||||
if (!QCA::haveSystemStore())
|
||||
printf("Warning: no root certs\n");
|
||||
else
|
||||
ssl->setTrustedCertificates(rootCerts);
|
||||
|
||||
ssl->startClient(host);
|
||||
}
|
||||
ssl->startClient(host);
|
||||
}
|
||||
|
||||
void sock_readyRead()
|
||||
{
|
||||
// We just do this to help doxygen...
|
||||
QCA::TLS *ssl = SecureTest::ssl;
|
||||
void sock_readyRead()
|
||||
{
|
||||
// We just do this to help doxygen...
|
||||
QCA::TLS *ssl = SecureTest::ssl;
|
||||
|
||||
ssl->writeIncoming(sock->readAll());
|
||||
}
|
||||
ssl->writeIncoming(sock->readAll());
|
||||
}
|
||||
|
||||
void sock_connectionClosed()
|
||||
{
|
||||
printf("\nConnection closed.\n");
|
||||
sock_done = true;
|
||||
void sock_connectionClosed()
|
||||
{
|
||||
printf("\nConnection closed.\n");
|
||||
sock_done = true;
|
||||
|
||||
if(ssl_done && sock_done)
|
||||
emit quit();
|
||||
}
|
||||
if (ssl_done && sock_done)
|
||||
emit quit();
|
||||
}
|
||||
|
||||
void sock_error(QAbstractSocket::SocketError x)
|
||||
{
|
||||
if(x == QAbstractSocket::RemoteHostClosedError)
|
||||
{
|
||||
sock_connectionClosed();
|
||||
return;
|
||||
}
|
||||
void sock_error(QAbstractSocket::SocketError x)
|
||||
{
|
||||
if (x == QAbstractSocket::RemoteHostClosedError) {
|
||||
sock_connectionClosed();
|
||||
return;
|
||||
}
|
||||
|
||||
printf("\nSocket error.\n");
|
||||
emit quit();
|
||||
}
|
||||
printf("\nSocket error.\n");
|
||||
emit quit();
|
||||
}
|
||||
|
||||
void ssl_handshaken()
|
||||
{
|
||||
// We just do this to help doxygen...
|
||||
QCA::TLS *ssl = SecureTest::ssl;
|
||||
void ssl_handshaken()
|
||||
{
|
||||
// We just do this to help doxygen...
|
||||
QCA::TLS *ssl = SecureTest::ssl;
|
||||
|
||||
QCA::TLS::IdentityResult r = ssl->peerIdentityResult();
|
||||
QCA::TLS::IdentityResult r = ssl->peerIdentityResult();
|
||||
|
||||
printf("Successful SSL handshake using %s (%i of %i bits)\n",
|
||||
qPrintable(ssl->cipherSuite()),
|
||||
ssl->cipherBits(),
|
||||
ssl->cipherMaxBits() );
|
||||
if(r != QCA::TLS::NoCertificate)
|
||||
{
|
||||
cert = ssl->peerCertificateChain().primary();
|
||||
if(!cert.isNull())
|
||||
showCertInfo(cert);
|
||||
}
|
||||
printf("Successful SSL handshake using %s (%i of %i bits)\n",
|
||||
qPrintable(ssl->cipherSuite()),
|
||||
ssl->cipherBits(),
|
||||
ssl->cipherMaxBits());
|
||||
if (r != QCA::TLS::NoCertificate) {
|
||||
cert = ssl->peerCertificateChain().primary();
|
||||
if (!cert.isNull())
|
||||
showCertInfo(cert);
|
||||
}
|
||||
|
||||
QString str = "Peer Identity: ";
|
||||
if(r == QCA::TLS::Valid)
|
||||
str += "Valid";
|
||||
else if(r == QCA::TLS::HostMismatch)
|
||||
str += "Error: Wrong certificate";
|
||||
else if(r == QCA::TLS::InvalidCertificate)
|
||||
str += "Error: Invalid certificate.\n -> Reason: " +
|
||||
validityToString(ssl->peerCertificateValidity());
|
||||
else
|
||||
str += "Error: No certificate";
|
||||
printf("%s\n", qPrintable(str));
|
||||
QString str = QStringLiteral("Peer Identity: ");
|
||||
if (r == QCA::TLS::Valid)
|
||||
str += QStringLiteral("Valid");
|
||||
else if (r == QCA::TLS::HostMismatch)
|
||||
str += QStringLiteral("Error: Wrong certificate");
|
||||
else if (r == QCA::TLS::InvalidCertificate)
|
||||
str += QStringLiteral("Error: Invalid certificate.\n -> Reason: ") +
|
||||
validityToString(ssl->peerCertificateValidity());
|
||||
else
|
||||
str += QStringLiteral("Error: No certificate");
|
||||
printf("%s\n", qPrintable(str));
|
||||
|
||||
ssl->continueAfterStep();
|
||||
ssl->continueAfterStep();
|
||||
|
||||
printf("Let's try a GET request now.\n");
|
||||
QString req = "GET / HTTP/1.0\nHost: " + host + "\n\n";
|
||||
ssl->write(req.toLatin1());
|
||||
}
|
||||
printf("Let's try a GET request now.\n");
|
||||
QString req = QStringLiteral("GET / HTTP/1.0\nHost: ") + host + QStringLiteral("\n\n");
|
||||
ssl->write(req.toLatin1());
|
||||
}
|
||||
|
||||
void ssl_certificateRequested()
|
||||
{
|
||||
// We just do this to help doxygen...
|
||||
QCA::TLS *ssl = SecureTest::ssl;
|
||||
void ssl_certificateRequested()
|
||||
{
|
||||
// We just do this to help doxygen...
|
||||
QCA::TLS *ssl = SecureTest::ssl;
|
||||
|
||||
printf("Server requested client certificate.\n");
|
||||
QList<QCA::CertificateInfoOrdered> issuerList = ssl->issuerList();
|
||||
if(!issuerList.isEmpty())
|
||||
{
|
||||
printf("Allowed issuers:\n");
|
||||
foreach(QCA::CertificateInfoOrdered i, issuerList)
|
||||
printf(" %s\n", qPrintable(i.toString()));
|
||||
}
|
||||
printf("Server requested client certificate.\n");
|
||||
QList<QCA::CertificateInfoOrdered> issuerList = ssl->issuerList();
|
||||
if (!issuerList.isEmpty()) {
|
||||
printf("Allowed issuers:\n");
|
||||
foreach (QCA::CertificateInfoOrdered i, issuerList)
|
||||
printf(" %s\n", qPrintable(i.toString()));
|
||||
}
|
||||
|
||||
ssl->continueAfterStep();
|
||||
}
|
||||
ssl->continueAfterStep();
|
||||
}
|
||||
|
||||
void ssl_readyRead()
|
||||
{
|
||||
// We just do this to help doxygen...
|
||||
QCA::TLS *ssl = SecureTest::ssl;
|
||||
void ssl_readyRead()
|
||||
{
|
||||
// We just do this to help doxygen...
|
||||
QCA::TLS *ssl = SecureTest::ssl;
|
||||
|
||||
QByteArray a = ssl->read();
|
||||
printf("%s", a.data());
|
||||
}
|
||||
QByteArray a = ssl->read();
|
||||
printf("%s", a.data());
|
||||
}
|
||||
|
||||
void ssl_readyReadOutgoing()
|
||||
{
|
||||
// We just do this to help doxygen...
|
||||
QCA::TLS *ssl = SecureTest::ssl;
|
||||
void ssl_readyReadOutgoing()
|
||||
{
|
||||
// We just do this to help doxygen...
|
||||
QCA::TLS *ssl = SecureTest::ssl;
|
||||
|
||||
sock->write(ssl->readOutgoing());
|
||||
}
|
||||
sock->write(ssl->readOutgoing());
|
||||
}
|
||||
|
||||
void ssl_closed()
|
||||
{
|
||||
printf("SSL session closed.\n");
|
||||
ssl_done = true;
|
||||
void ssl_closed()
|
||||
{
|
||||
printf("SSL session closed.\n");
|
||||
ssl_done = true;
|
||||
|
||||
if(ssl_done && sock_done)
|
||||
emit quit();
|
||||
}
|
||||
if (ssl_done && sock_done)
|
||||
emit quit();
|
||||
}
|
||||
|
||||
void ssl_error()
|
||||
{
|
||||
// We just do this to help doxygen...
|
||||
QCA::TLS *ssl = SecureTest::ssl;
|
||||
void ssl_error()
|
||||
{
|
||||
// We just do this to help doxygen...
|
||||
QCA::TLS *ssl = SecureTest::ssl;
|
||||
|
||||
int x = ssl->errorCode();
|
||||
if(x == QCA::TLS::ErrorHandshake)
|
||||
{
|
||||
printf("SSL Handshake Error!\n");
|
||||
emit quit();
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("SSL Error!\n");
|
||||
emit quit();
|
||||
}
|
||||
}
|
||||
int x = ssl->errorCode();
|
||||
if (x == QCA::TLS::ErrorHandshake) {
|
||||
printf("SSL Handshake Error!\n");
|
||||
emit quit();
|
||||
} else {
|
||||
printf("SSL Error!\n");
|
||||
emit quit();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
QString host;
|
||||
QTcpSocket *sock;
|
||||
QCA::TLS *ssl;
|
||||
QCA::Certificate cert;
|
||||
bool sock_done, ssl_done;
|
||||
QString host;
|
||||
QTcpSocket * sock;
|
||||
QCA::TLS * ssl;
|
||||
QCA::Certificate cert;
|
||||
bool sock_done, ssl_done;
|
||||
};
|
||||
|
||||
#include "ssltest.moc"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
QCA::Initializer init;
|
||||
QCA::Initializer init;
|
||||
|
||||
QCoreApplication app(argc, argv);
|
||||
QString host = argc > 1 ? argv[1] : "andbit.net";
|
||||
QCoreApplication app(argc, argv);
|
||||
QString host = argc > 1 ? QString::fromLocal8Bit(argv[1]) : QStringLiteral("andbit.net");
|
||||
|
||||
if(!QCA::isSupported("tls"))
|
||||
{
|
||||
printf("TLS not supported!\n");
|
||||
return 1;
|
||||
}
|
||||
if (!QCA::isSupported("tls")) {
|
||||
printf("TLS not supported!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
SecureTest *s = new SecureTest;
|
||||
QObject::connect(s, SIGNAL(quit()), &app, SLOT(quit()));
|
||||
s->start(host);
|
||||
app.exec();
|
||||
delete s;
|
||||
SecureTest *s = new SecureTest;
|
||||
QObject::connect(s, &SecureTest::quit, &app, &QCoreApplication::quit);
|
||||
s->start(host);
|
||||
app.exec();
|
||||
delete s;
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,9 +1,8 @@
|
||||
set(tlssocket_bin_moc_SRCS tlssocket.cpp)
|
||||
set(tlssocket_bin_nonmoc_SRCS main.cpp)
|
||||
|
||||
MY_AUTOMOC( tlssocket_bin_moc_SRCS)
|
||||
|
||||
add_executable(tlssocket ${tlssocket_bin_moc_SRCS} ${tlssocket_bin_nonmoc_SRCS})
|
||||
add_executable(tlssocket tlssocket.cpp main.cpp)
|
||||
|
||||
target_link_qca_libraries(tlssocket)
|
||||
target_link_libraries(tlssocket ${QT_QTNETWORK_LIBRARY})
|
||||
if(QT6)
|
||||
target_link_libraries(tlssocket Qt6::Network)
|
||||
else()
|
||||
target_link_libraries(tlssocket Qt5::Network)
|
||||
endif()
|
||||
|
@ -25,14 +25,14 @@
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
QCA::Initializer init;
|
||||
QCoreApplication qapp(argc, argv);
|
||||
QCA::Initializer init;
|
||||
QCoreApplication qapp(argc, argv);
|
||||
|
||||
TLSSocket socket;
|
||||
socket.connectToHostEncrypted("www.paypal.com", 443);
|
||||
socket.write("GET / HTTP/1.0\r\n\r\n");
|
||||
while(socket.waitForReadyRead())
|
||||
printf("%s", socket.readAll().data());
|
||||
TLSSocket socket;
|
||||
socket.connectToHostEncrypted(QStringLiteral("www.paypal.com"), 443);
|
||||
socket.write("GET / HTTP/1.0\r\n\r\n");
|
||||
while (socket.waitForReadyRead())
|
||||
printf("%s", socket.readAll().constData());
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
@ -27,191 +27,196 @@
|
||||
|
||||
class TLSSocket::Private : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
public:
|
||||
TLSSocket *q;
|
||||
QTcpSocket *sock;
|
||||
QCA::TLS *tls;
|
||||
QString host;
|
||||
bool encrypted;
|
||||
bool error, done;
|
||||
QByteArray readbuf, writebuf;
|
||||
QCA::Synchronizer sync;
|
||||
bool waiting;
|
||||
TLSSocket * q;
|
||||
QTcpSocket * sock;
|
||||
QCA::TLS * tls;
|
||||
QString host;
|
||||
bool encrypted;
|
||||
bool error, done;
|
||||
QByteArray readbuf, writebuf;
|
||||
QCA::Synchronizer sync;
|
||||
bool waiting;
|
||||
|
||||
Private(TLSSocket *_q) : QObject(_q), q(_q), sync(_q)
|
||||
{
|
||||
sock = new QTcpSocket(this);
|
||||
connect(sock, SIGNAL(connected()), SLOT(sock_connected()));
|
||||
connect(sock, SIGNAL(readyRead()), SLOT(sock_readyRead()));
|
||||
connect(sock, SIGNAL(bytesWritten(qint64)), SLOT(sock_bytesWritten(qint64)));
|
||||
connect(sock, SIGNAL(error(QAbstractSocket::SocketError)), SLOT(sock_error(QAbstractSocket::SocketError)));
|
||||
Private(TLSSocket *_q)
|
||||
: QObject(_q)
|
||||
, q(_q)
|
||||
, sync(_q)
|
||||
{
|
||||
sock = new QTcpSocket(this);
|
||||
connect(sock, &QTcpSocket::connected, this, &TLSSocket::Private::sock_connected);
|
||||
connect(sock, &QTcpSocket::readyRead, this, &TLSSocket::Private::sock_readyRead);
|
||||
connect(sock, &QTcpSocket::bytesWritten, this, &TLSSocket::Private::sock_bytesWritten);
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
|
||||
connect(sock, &QTcpSocket::errorOccurred, this, &TLSSocket::Private::sock_error);
|
||||
#else
|
||||
connect(sock,
|
||||
QOverload<QAbstractSocket::SocketError>::of(&QTcpSocket::error),
|
||||
this,
|
||||
&TLSSocket::Private::sock_error);
|
||||
#endif
|
||||
|
||||
tls = new QCA::TLS(this);
|
||||
connect(tls, SIGNAL(handshaken()), SLOT(tls_handshaken()));
|
||||
connect(tls, SIGNAL(readyRead()), SLOT(tls_readyRead()));
|
||||
connect(tls, SIGNAL(readyReadOutgoing()), SLOT(tls_readyReadOutgoing()));
|
||||
connect(tls, SIGNAL(closed()), SLOT(tls_closed()));
|
||||
connect(tls, SIGNAL(error()), SLOT(tls_error()));
|
||||
tls->setTrustedCertificates(QCA::systemStore());
|
||||
encrypted = false;
|
||||
error = false;
|
||||
waiting = false;
|
||||
done = false;
|
||||
}
|
||||
tls = new QCA::TLS(this);
|
||||
connect(tls, &QCA::TLS::handshaken, this, &TLSSocket::Private::tls_handshaken);
|
||||
connect(tls, &QCA::TLS::readyRead, this, &TLSSocket::Private::tls_readyRead);
|
||||
connect(tls, &QCA::TLS::readyReadOutgoing, this, &TLSSocket::Private::tls_readyReadOutgoing);
|
||||
connect(tls, &QCA::TLS::closed, this, &TLSSocket::Private::tls_closed);
|
||||
connect(tls, &QCA::TLS::error, this, &TLSSocket::Private::tls_error);
|
||||
tls->setTrustedCertificates(QCA::systemStore());
|
||||
encrypted = false;
|
||||
error = false;
|
||||
waiting = false;
|
||||
done = false;
|
||||
}
|
||||
|
||||
bool waitForReadyRead(int msecs)
|
||||
{
|
||||
waiting = true;
|
||||
bool ok = sync.waitForCondition(msecs);
|
||||
//while(1)
|
||||
// QCoreApplication::instance()->processEvents();
|
||||
waiting = false;
|
||||
if(error || done)
|
||||
return false;
|
||||
return ok;
|
||||
}
|
||||
bool waitForReadyRead(int msecs)
|
||||
{
|
||||
waiting = true;
|
||||
bool ok = sync.waitForCondition(msecs);
|
||||
// while(1)
|
||||
// QCoreApplication::instance()->processEvents();
|
||||
waiting = false;
|
||||
if (error || done)
|
||||
return false;
|
||||
return ok;
|
||||
}
|
||||
|
||||
private slots:
|
||||
void sock_connected()
|
||||
{
|
||||
//printf("sock connected\n");
|
||||
tls->startClient(host);
|
||||
}
|
||||
private Q_SLOTS:
|
||||
void sock_connected()
|
||||
{
|
||||
// printf("sock connected\n");
|
||||
tls->startClient(host);
|
||||
}
|
||||
|
||||
void sock_readyRead()
|
||||
{
|
||||
//printf("sock ready read\n");
|
||||
QByteArray buf = sock->readAll();
|
||||
//printf("%d bytes\n", buf.size());
|
||||
tls->writeIncoming(buf);
|
||||
}
|
||||
void sock_readyRead()
|
||||
{
|
||||
// printf("sock ready read\n");
|
||||
QByteArray buf = sock->readAll();
|
||||
// printf("%d bytes\n", buf.size());
|
||||
tls->writeIncoming(buf);
|
||||
}
|
||||
|
||||
void sock_bytesWritten(qint64 x)
|
||||
{
|
||||
Q_UNUSED(x);
|
||||
//printf("sock bytes written: %d\n", (int)x);
|
||||
}
|
||||
void sock_bytesWritten(qint64 x)
|
||||
{
|
||||
Q_UNUSED(x);
|
||||
// printf("sock bytes written: %d\n", (int)x);
|
||||
}
|
||||
|
||||
void sock_error(QAbstractSocket::SocketError x)
|
||||
{
|
||||
//printf("sock error: %d\n", x);
|
||||
Q_UNUSED(x);
|
||||
done = true;
|
||||
if(waiting)
|
||||
sync.conditionMet();
|
||||
}
|
||||
void sock_error(QAbstractSocket::SocketError x)
|
||||
{
|
||||
// printf("sock error: %d\n", x);
|
||||
Q_UNUSED(x);
|
||||
done = true;
|
||||
if (waiting)
|
||||
sync.conditionMet();
|
||||
}
|
||||
|
||||
void tls_handshaken()
|
||||
{
|
||||
//printf("tls handshaken\n");
|
||||
if(tls->peerIdentityResult() != QCA::TLS::Valid)
|
||||
{
|
||||
printf("not valid\n");
|
||||
sock->abort();
|
||||
tls->reset();
|
||||
error = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
//printf("valid\n");
|
||||
encrypted = true;
|
||||
//printf("%d bytes in writebuf\n", writebuf.size());
|
||||
if(!writebuf.isEmpty())
|
||||
{
|
||||
//printf("[%s]\n", writebuf.data());
|
||||
tls->write(writebuf);
|
||||
writebuf.clear();
|
||||
}
|
||||
}
|
||||
if(waiting)
|
||||
sync.conditionMet();
|
||||
}
|
||||
void tls_handshaken()
|
||||
{
|
||||
// printf("tls handshaken\n");
|
||||
if (tls->peerIdentityResult() != QCA::TLS::Valid) {
|
||||
printf("not valid\n");
|
||||
sock->abort();
|
||||
tls->reset();
|
||||
error = true;
|
||||
} else {
|
||||
// printf("valid\n");
|
||||
encrypted = true;
|
||||
// printf("%d bytes in writebuf\n", writebuf.size());
|
||||
if (!writebuf.isEmpty()) {
|
||||
// printf("[%s]\n", writebuf.data());
|
||||
tls->write(writebuf);
|
||||
writebuf.clear();
|
||||
}
|
||||
}
|
||||
if (waiting)
|
||||
sync.conditionMet();
|
||||
}
|
||||
|
||||
void tls_readyRead()
|
||||
{
|
||||
//printf("tls ready read\n");
|
||||
if(waiting)
|
||||
sync.conditionMet();
|
||||
}
|
||||
void tls_readyRead()
|
||||
{
|
||||
// printf("tls ready read\n");
|
||||
if (waiting)
|
||||
sync.conditionMet();
|
||||
}
|
||||
|
||||
void tls_readyReadOutgoing()
|
||||
{
|
||||
//printf("tls ready read outgoing\n");
|
||||
QByteArray buf = tls->readOutgoing();
|
||||
//printf("%d bytes\n", buf.size());
|
||||
sock->write(buf);
|
||||
}
|
||||
void tls_readyReadOutgoing()
|
||||
{
|
||||
// printf("tls ready read outgoing\n");
|
||||
QByteArray buf = tls->readOutgoing();
|
||||
// printf("%d bytes\n", buf.size());
|
||||
sock->write(buf);
|
||||
}
|
||||
|
||||
void tls_closed()
|
||||
{
|
||||
//printf("tls closed\n");
|
||||
}
|
||||
void tls_closed()
|
||||
{
|
||||
// printf("tls closed\n");
|
||||
}
|
||||
|
||||
void tls_error()
|
||||
{
|
||||
//printf("tls error\n");
|
||||
}
|
||||
void tls_error()
|
||||
{
|
||||
// printf("tls error\n");
|
||||
}
|
||||
};
|
||||
|
||||
TLSSocket::TLSSocket(QObject *parent)
|
||||
:QTcpSocket(parent)
|
||||
: QTcpSocket(parent)
|
||||
{
|
||||
d = new Private(this);
|
||||
|
||||
d = new Private(this);
|
||||
}
|
||||
|
||||
TLSSocket::~TLSSocket()
|
||||
{
|
||||
delete d;
|
||||
delete d;
|
||||
}
|
||||
|
||||
void TLSSocket::connectToHostEncrypted(const QString &host, quint16 port)
|
||||
{
|
||||
d->host = host;
|
||||
setOpenMode(QIODevice::ReadWrite);
|
||||
d->sock->connectToHost(host, port);
|
||||
d->host = host;
|
||||
setOpenMode(QIODevice::ReadWrite);
|
||||
d->sock->connectToHost(host, port);
|
||||
}
|
||||
|
||||
QCA::TLS *TLSSocket::tls()
|
||||
{
|
||||
return d->tls;
|
||||
return d->tls;
|
||||
}
|
||||
|
||||
bool TLSSocket::waitForReadyRead(int msecs)
|
||||
{
|
||||
/*if(d->readbuf.isEmpty())
|
||||
return false;
|
||||
/*if(d->readbuf.isEmpty())
|
||||
return false;
|
||||
|
||||
if(d->tls->bytesAvailable() == 0)
|
||||
return false;*/
|
||||
if(d->tls->bytesAvailable() == 0)
|
||||
return false;*/
|
||||
|
||||
return d->waitForReadyRead(msecs);
|
||||
return d->waitForReadyRead(msecs);
|
||||
}
|
||||
|
||||
qint64 TLSSocket::readData(char *data, qint64 maxlen)
|
||||
{
|
||||
if(!d->error)
|
||||
d->readbuf += d->tls->read();
|
||||
unsigned char *p = (unsigned char *)d->readbuf.data();
|
||||
int size = d->readbuf.size();
|
||||
int readsize = qMin(size, (int)maxlen);
|
||||
int newsize = size - readsize;
|
||||
memcpy(data, p, readsize);
|
||||
memmove(p, p + readsize, newsize);
|
||||
d->readbuf.resize(newsize);
|
||||
return readsize;
|
||||
if (!d->error)
|
||||
d->readbuf += d->tls->read();
|
||||
unsigned char *p = (unsigned char *)d->readbuf.data();
|
||||
int size = d->readbuf.size();
|
||||
int readsize = qMin(size, (int)maxlen);
|
||||
int newsize = size - readsize;
|
||||
memcpy(data, p, readsize);
|
||||
memmove(p, p + readsize, newsize);
|
||||
d->readbuf.resize(newsize);
|
||||
return readsize;
|
||||
}
|
||||
|
||||
qint64 TLSSocket::writeData(const char *data, qint64 len)
|
||||
{
|
||||
//printf("write %d bytes\n", (int)len);
|
||||
QByteArray buf(data, len);
|
||||
if(d->encrypted)
|
||||
d->tls->write(buf);
|
||||
else
|
||||
d->writebuf += buf;
|
||||
return len;
|
||||
// printf("write %d bytes\n", (int)len);
|
||||
QByteArray buf(data, len);
|
||||
if (d->encrypted)
|
||||
d->tls->write(buf);
|
||||
else
|
||||
d->writebuf += buf;
|
||||
return len;
|
||||
}
|
||||
|
||||
#include "tlssocket.moc"
|
||||
|
@ -21,29 +21,30 @@
|
||||
|
||||
#ifndef TLSSOCKET_H
|
||||
|
||||
#include <QtCrypto>
|
||||
#include <QTcpSocket>
|
||||
#include <QtCrypto>
|
||||
|
||||
class TLSSocket : public QTcpSocket
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
TLSSocket(QObject *parent = 0);
|
||||
~TLSSocket();
|
||||
TLSSocket(QObject *parent = nullptr);
|
||||
~TLSSocket() override;
|
||||
|
||||
void connectToHostEncrypted(const QString &host, quint16 port);
|
||||
QCA::TLS *tls();
|
||||
void connectToHostEncrypted(const QString &host, quint16 port);
|
||||
QCA::TLS *tls();
|
||||
|
||||
bool waitForReadyRead(int msecs = -1);
|
||||
bool waitForReadyRead(int msecs = -1) override;
|
||||
|
||||
protected:
|
||||
// from qiodevice
|
||||
virtual qint64 readData(char *data, qint64 maxlen);
|
||||
virtual qint64 writeData(const char *data, qint64 len);
|
||||
// from qiodevice
|
||||
qint64 readData(char *data, qint64 maxlen) override;
|
||||
qint64 writeData(const char *data, qint64 len) override;
|
||||
|
||||
private:
|
||||
class Private;
|
||||
friend class Private;
|
||||
Private *d;
|
||||
class Private;
|
||||
friend class Private;
|
||||
Private *d;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
10
hooks/pre-commit
Normal file
10
hooks/pre-commit
Normal 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
|
@ -33,16 +33,16 @@
|
||||
#ifndef QCA_H
|
||||
#define QCA_H
|
||||
|
||||
#include "qca_core.h"
|
||||
#include "qca_textfilter.h"
|
||||
#include "qca_basic.h"
|
||||
#include "qca_publickey.h"
|
||||
#include "qca_cert.h"
|
||||
#include "qca_core.h"
|
||||
#include "qca_keystore.h"
|
||||
#include "qca_publickey.h"
|
||||
#include "qca_safetimer.h"
|
||||
#include "qca_securelayer.h"
|
||||
#include "qca_securemessage.h"
|
||||
#include "qca_textfilter.h"
|
||||
#include "qcaprovider.h"
|
||||
#include "qpipe.h"
|
||||
#include "qca_safetimer.h"
|
||||
|
||||
#endif
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -22,7 +22,7 @@
|
||||
/**
|
||||
\file qca_export.h
|
||||
|
||||
Preprocessor magic to allow export of library symbols.
|
||||
Preprocessor magic to allow export of library symbols.
|
||||
|
||||
This is strictly internal.
|
||||
|
||||
@ -37,16 +37,16 @@
|
||||
#include <QtGlobal>
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
# ifndef QCA_STATIC
|
||||
# ifdef QCA_MAKEDLL
|
||||
# define QCA_EXPORT Q_DECL_EXPORT
|
||||
# else
|
||||
# define QCA_EXPORT Q_DECL_IMPORT
|
||||
# endif
|
||||
# endif
|
||||
#ifndef QCA_STATIC
|
||||
#ifdef QCA_MAKEDLL
|
||||
#define QCA_EXPORT Q_DECL_EXPORT
|
||||
#else
|
||||
#define QCA_EXPORT Q_DECL_IMPORT
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#ifndef QCA_EXPORT
|
||||
# define QCA_EXPORT
|
||||
#define QCA_EXPORT
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -32,37 +32,41 @@ namespace QCA {
|
||||
|
||||
class QCA_EXPORT SafeTimer : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
public:
|
||||
SafeTimer(QObject *parent = 0);
|
||||
~SafeTimer();
|
||||
SafeTimer(QObject *parent = nullptr);
|
||||
~SafeTimer() override;
|
||||
|
||||
int interval() const;
|
||||
bool isActive() const;
|
||||
bool isSingleShot() const;
|
||||
void setInterval(int msec);
|
||||
void setSingleShot(bool singleShot);
|
||||
int timerId() const;
|
||||
int interval() const;
|
||||
bool isActive() const;
|
||||
bool isSingleShot() const;
|
||||
void setInterval(int msec);
|
||||
void setSingleShot(bool singleShot);
|
||||
int timerId() const;
|
||||
|
||||
public Q_SLOTS:
|
||||
void start(int msec);
|
||||
void start();
|
||||
void stop();
|
||||
void start(int msec);
|
||||
void start();
|
||||
void stop();
|
||||
|
||||
Q_SIGNALS:
|
||||
void timeout();
|
||||
void timeout();
|
||||
|
||||
protected:
|
||||
bool event(QEvent *event);
|
||||
void timerEvent(QTimerEvent *event);
|
||||
bool event(QEvent *event) override;
|
||||
void timerEvent(QTimerEvent *event) override;
|
||||
|
||||
private:
|
||||
// Functions is used internally. Outer world mustn't have access them.
|
||||
void startTimer() {}
|
||||
void killTimer(int) {}
|
||||
// Functions is used internally. Outer world mustn't have access them.
|
||||
void startTimer()
|
||||
{
|
||||
}
|
||||
void killTimer(int)
|
||||
{
|
||||
}
|
||||
|
||||
class Private;
|
||||
Private *d;
|
||||
class Private;
|
||||
Private *d;
|
||||
};
|
||||
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -43,7 +43,7 @@ namespace QCA {
|
||||
Superclass for text based filtering algorithms
|
||||
|
||||
This differs from Filter in that it has the concept
|
||||
of an algorithm that works in two directions, and
|
||||
of an algorithm that works in two directions, and
|
||||
supports operations on QString arguments.
|
||||
|
||||
\ingroup UserAPI
|
||||
@ -51,107 +51,107 @@ namespace QCA {
|
||||
class QCA_EXPORT TextFilter : public Filter
|
||||
{
|
||||
public:
|
||||
/**
|
||||
Standard constructor
|
||||
/**
|
||||
Standard constructor
|
||||
|
||||
\param dir the Direction that this TextFilter
|
||||
should use.
|
||||
*/
|
||||
TextFilter(Direction dir);
|
||||
\param dir the Direction that this TextFilter
|
||||
should use.
|
||||
*/
|
||||
TextFilter(Direction dir);
|
||||
|
||||
/**
|
||||
Reset the TextFilter
|
||||
/**
|
||||
Reset the TextFilter
|
||||
|
||||
\param dir the Direction that this TextFilter
|
||||
should use.
|
||||
*/
|
||||
void setup(Direction dir);
|
||||
\param dir the Direction that this TextFilter
|
||||
should use.
|
||||
*/
|
||||
void setup(Direction dir);
|
||||
|
||||
/**
|
||||
The direction the TextFilter is set up to use
|
||||
*/
|
||||
Direction direction() const;
|
||||
/**
|
||||
The direction the TextFilter is set up to use
|
||||
*/
|
||||
Direction direction() const;
|
||||
|
||||
/**
|
||||
Process an array in the "forward" direction,
|
||||
returning an array
|
||||
/**
|
||||
Process an array in the "forward" direction,
|
||||
returning an array
|
||||
|
||||
This method runs in the forward direction, so
|
||||
for something like a Base64 encoding, it takes
|
||||
the "native" array, and returns that array
|
||||
encoded in base64.
|
||||
This method runs in the forward direction, so
|
||||
for something like a Base64 encoding, it takes
|
||||
the "native" array, and returns that array
|
||||
encoded in base64.
|
||||
|
||||
\param a the array to encode
|
||||
*/
|
||||
MemoryRegion encode(const MemoryRegion &a);
|
||||
\param a the array to encode
|
||||
*/
|
||||
MemoryRegion encode(const MemoryRegion &a);
|
||||
|
||||
/**
|
||||
Process an array in the "reverse" direction,
|
||||
returning an array
|
||||
/**
|
||||
Process an array in the "reverse" direction,
|
||||
returning an array
|
||||
|
||||
This method runs in the reverse direction, so
|
||||
for something like a Base64 encoding, it takes
|
||||
a Base64 encoded array, and returns the "native"
|
||||
representation.
|
||||
This method runs in the reverse direction, so
|
||||
for something like a Base64 encoding, it takes
|
||||
a Base64 encoded array, and returns the "native"
|
||||
representation.
|
||||
|
||||
\param a the array to decode
|
||||
*/
|
||||
MemoryRegion decode(const MemoryRegion &a);
|
||||
\param a the array to decode
|
||||
*/
|
||||
MemoryRegion decode(const MemoryRegion &a);
|
||||
|
||||
/**
|
||||
Process an array in the "forward" direction,
|
||||
returning a QString
|
||||
/**
|
||||
Process an array in the "forward" direction,
|
||||
returning a QString
|
||||
|
||||
This is equivalent to encode(), except
|
||||
that it returns a QString, rather than a
|
||||
byte array.
|
||||
This is equivalent to encode(), except
|
||||
that it returns a QString, rather than a
|
||||
byte array.
|
||||
|
||||
\param a the array to encode
|
||||
*/
|
||||
QString arrayToString(const MemoryRegion &a);
|
||||
\param a the array to encode
|
||||
*/
|
||||
QString arrayToString(const MemoryRegion &a);
|
||||
|
||||
/**
|
||||
Process an string in the "reverse" direction,
|
||||
returning a byte array
|
||||
/**
|
||||
Process an string in the "reverse" direction,
|
||||
returning a byte array
|
||||
|
||||
This is equivalent to decode(), except
|
||||
that it takes a QString, rather than a
|
||||
byte array.
|
||||
This is equivalent to decode(), except
|
||||
that it takes a QString, rather than a
|
||||
byte array.
|
||||
|
||||
\param s the array to decode
|
||||
*/
|
||||
MemoryRegion stringToArray(const QString &s);
|
||||
\param s the array to decode
|
||||
*/
|
||||
MemoryRegion stringToArray(const QString &s);
|
||||
|
||||
/**
|
||||
Process a string in the "forward" direction,
|
||||
returning a string
|
||||
/**
|
||||
Process a string in the "forward" direction,
|
||||
returning a string
|
||||
|
||||
This is equivalent to encode(), except
|
||||
that it takes and returns a QString, rather than
|
||||
byte arrays.
|
||||
This is equivalent to encode(), except
|
||||
that it takes and returns a QString, rather than
|
||||
byte arrays.
|
||||
|
||||
\param s the string to encode
|
||||
*/
|
||||
QString encodeString(const QString &s);
|
||||
\param s the string to encode
|
||||
*/
|
||||
QString encodeString(const QString &s);
|
||||
|
||||
/**
|
||||
Process a string in the "reverse" direction,
|
||||
returning a string
|
||||
/**
|
||||
Process a string in the "reverse" direction,
|
||||
returning a string
|
||||
|
||||
This is equivalent to decode(), except
|
||||
that it takes and returns a QString, rather than
|
||||
byte arrays.
|
||||
This is equivalent to decode(), except
|
||||
that it takes and returns a QString, rather than
|
||||
byte arrays.
|
||||
|
||||
\param s the string to decode
|
||||
*/
|
||||
QString decodeString(const QString &s);
|
||||
\param s the string to decode
|
||||
*/
|
||||
QString decodeString(const QString &s);
|
||||
|
||||
protected:
|
||||
/**
|
||||
Internal state variable for the Direction
|
||||
that the filter operates in
|
||||
*/
|
||||
Direction _dir;
|
||||
/**
|
||||
Internal state variable for the Direction
|
||||
that the filter operates in
|
||||
*/
|
||||
Direction _dir;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -164,62 +164,62 @@ protected:
|
||||
class QCA_EXPORT Hex : public TextFilter
|
||||
{
|
||||
public:
|
||||
/**
|
||||
Standard constructor
|
||||
/**
|
||||
Standard constructor
|
||||
|
||||
\param dir the Direction that should be used.
|
||||
\param dir the Direction that should be used.
|
||||
|
||||
\note The direction can be changed using
|
||||
the setup() call.
|
||||
*/
|
||||
Hex(Direction dir = Encode);
|
||||
\note The direction can be changed using
|
||||
the setup() call.
|
||||
*/
|
||||
Hex(Direction dir = Encode);
|
||||
|
||||
/**
|
||||
Reset the internal state.
|
||||
/**
|
||||
Reset the internal state.
|
||||
|
||||
This is useful to reuse an existing Hex object
|
||||
*/
|
||||
virtual void clear();
|
||||
This is useful to reuse an existing Hex object
|
||||
*/
|
||||
void clear() override;
|
||||
|
||||
/**
|
||||
Process more data, returning the corresponding
|
||||
encoded or decoded (depending on the Direction
|
||||
set in the constructor or setup() call) representation.
|
||||
/**
|
||||
Process more data, returning the corresponding
|
||||
encoded or decoded (depending on the Direction
|
||||
set in the constructor or setup() call) representation.
|
||||
|
||||
If you find yourself with code that only calls
|
||||
this method once, you might be better off using
|
||||
encode() or decode(). Similarly, if the data is
|
||||
really a string, you might be better off using
|
||||
arrayToString(), encodeString(), stringToArray()
|
||||
or decodeString().
|
||||
If you find yourself with code that only calls
|
||||
this method once, you might be better off using
|
||||
encode() or decode(). Similarly, if the data is
|
||||
really a string, you might be better off using
|
||||
arrayToString(), encodeString(), stringToArray()
|
||||
or decodeString().
|
||||
|
||||
\param a the array containing data to process
|
||||
*/
|
||||
virtual MemoryRegion update(const MemoryRegion &a);
|
||||
\param a the array containing data to process
|
||||
*/
|
||||
MemoryRegion update(const MemoryRegion &a) override;
|
||||
|
||||
/**
|
||||
Complete the algorithm
|
||||
/**
|
||||
Complete the algorithm
|
||||
|
||||
\return any remaining output. Because of the way
|
||||
hexadecimal encoding works, this will return a
|
||||
zero length array - any output will have been returned
|
||||
from the update() call.
|
||||
*/
|
||||
virtual MemoryRegion final();
|
||||
\return any remaining output. Because of the way
|
||||
hexadecimal encoding works, this will return a
|
||||
zero length array - any output will have been returned
|
||||
from the update() call.
|
||||
*/
|
||||
MemoryRegion final() override;
|
||||
|
||||
/**
|
||||
Test if an update() or final() call succeeded.
|
||||
|
||||
\return true if the previous call succeeded
|
||||
*/
|
||||
virtual bool ok() const;
|
||||
/**
|
||||
Test if an update() or final() call succeeded.
|
||||
|
||||
\return true if the previous call succeeded
|
||||
*/
|
||||
bool ok() const override;
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(Hex)
|
||||
Q_DISABLE_COPY(Hex)
|
||||
|
||||
uchar val;
|
||||
bool partial;
|
||||
bool _ok;
|
||||
uchar val;
|
||||
bool partial;
|
||||
bool _ok;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -232,94 +232,94 @@ private:
|
||||
class QCA_EXPORT Base64 : public TextFilter
|
||||
{
|
||||
public:
|
||||
/**
|
||||
Standard constructor
|
||||
/**
|
||||
Standard constructor
|
||||
|
||||
\param dir the Direction that should be used.
|
||||
\param dir the Direction that should be used.
|
||||
|
||||
\note The direction can be changed using
|
||||
the setup() call.
|
||||
*/
|
||||
Base64(Direction dir = Encode);
|
||||
\note The direction can be changed using
|
||||
the setup() call.
|
||||
*/
|
||||
Base64(Direction dir = Encode);
|
||||
|
||||
/**
|
||||
Returns true if line breaks are enabled
|
||||
*/
|
||||
bool lineBreaksEnabled() const;
|
||||
/**
|
||||
Returns true if line breaks are enabled
|
||||
*/
|
||||
bool lineBreaksEnabled() const;
|
||||
|
||||
/**
|
||||
Returns the line break column
|
||||
*/
|
||||
int lineBreaksColumn() const;
|
||||
/**
|
||||
Returns the line break column
|
||||
*/
|
||||
int lineBreaksColumn() const;
|
||||
|
||||
/**
|
||||
Sets line break mode. If enabled, linebreaks will be
|
||||
added to encoded output or accepted in encoded input.
|
||||
If disabled, linebreaks in encoded input will cause
|
||||
a failure to decode. The default is disabled.
|
||||
/**
|
||||
Sets line break mode. If enabled, linebreaks will be
|
||||
added to encoded output or accepted in encoded input.
|
||||
If disabled, linebreaks in encoded input will cause
|
||||
a failure to decode. The default is disabled.
|
||||
|
||||
\param b whether to enable line breaks (true) or disable line breaks (false)
|
||||
*/
|
||||
void setLineBreaksEnabled(bool b);
|
||||
\param b whether to enable line breaks (true) or disable line breaks (false)
|
||||
*/
|
||||
void setLineBreaksEnabled(bool b);
|
||||
|
||||
/**
|
||||
Sets the column that linebreaks should be inserted at
|
||||
when encoding.
|
||||
/**
|
||||
Sets the column that linebreaks should be inserted at
|
||||
when encoding.
|
||||
|
||||
\param column the column number that line breaks should be inserted at.
|
||||
*/
|
||||
void setLineBreaksColumn(int column);
|
||||
\param column the column number that line breaks should be inserted at.
|
||||
*/
|
||||
void setLineBreaksColumn(int column);
|
||||
|
||||
/**
|
||||
Reset the internal state. This is useful to
|
||||
reuse an existing Base64 object
|
||||
*/
|
||||
virtual void clear();
|
||||
/**
|
||||
Reset the internal state. This is useful to
|
||||
reuse an existing Base64 object
|
||||
*/
|
||||
void clear() override;
|
||||
|
||||
/**
|
||||
Process more data, returning the corresponding
|
||||
encoded or decoded (depending on the Direction
|
||||
set in the constructor or setup() call) representation.
|
||||
/**
|
||||
Process more data, returning the corresponding
|
||||
encoded or decoded (depending on the Direction
|
||||
set in the constructor or setup() call) representation.
|
||||
|
||||
If you find yourself with code that only calls
|
||||
this method once, you might be better off using
|
||||
encode() or decode(). Similarly, if the data is
|
||||
really a string, you might be better off using
|
||||
arrayToString(), encodeString(), stringToArray()
|
||||
or decodeString().
|
||||
If you find yourself with code that only calls
|
||||
this method once, you might be better off using
|
||||
encode() or decode(). Similarly, if the data is
|
||||
really a string, you might be better off using
|
||||
arrayToString(), encodeString(), stringToArray()
|
||||
or decodeString().
|
||||
|
||||
\param a the array containing data to process
|
||||
*/
|
||||
virtual MemoryRegion update(const MemoryRegion &a);
|
||||
\param a the array containing data to process
|
||||
*/
|
||||
MemoryRegion update(const MemoryRegion &a) override;
|
||||
|
||||
/**
|
||||
Complete the algorithm
|
||||
/**
|
||||
Complete the algorithm
|
||||
|
||||
\return any remaining output. Because of the way
|
||||
Base64 encoding works, you will get either an
|
||||
empty array, or an array containing one or two
|
||||
"=" (equals, 0x3D) characters.
|
||||
*/
|
||||
virtual MemoryRegion final();
|
||||
\return any remaining output. Because of the way
|
||||
Base64 encoding works, you will get either an
|
||||
empty array, or an array containing one or two
|
||||
"=" (equals, 0x3D) characters.
|
||||
*/
|
||||
MemoryRegion final() override;
|
||||
|
||||
/**
|
||||
Test if an update() or final() call succeeded.
|
||||
|
||||
\return true if the previous call succeeded
|
||||
*/
|
||||
virtual bool ok() const;
|
||||
/**
|
||||
Test if an update() or final() call succeeded.
|
||||
|
||||
\return true if the previous call succeeded
|
||||
*/
|
||||
bool ok() const override;
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(Base64)
|
||||
Q_DISABLE_COPY(Base64)
|
||||
|
||||
QByteArray partial;
|
||||
bool _ok;
|
||||
int col;
|
||||
bool _lb_enabled;
|
||||
int _lb_column;
|
||||
QByteArray partial;
|
||||
bool _ok;
|
||||
int col;
|
||||
bool _lb_enabled;
|
||||
int _lb_column;
|
||||
|
||||
class Private;
|
||||
Private *d;
|
||||
class Private;
|
||||
Private *d;
|
||||
};
|
||||
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -34,13 +34,13 @@
|
||||
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
||||
|
||||
#ifndef QPIPE_NO_SECURE
|
||||
# define QPIPE_SECURE
|
||||
#define QPIPE_SECURE
|
||||
#endif
|
||||
|
||||
#ifdef QPIPE_SECURE
|
||||
# include "QtCrypto"
|
||||
#include "QtCrypto"
|
||||
#else
|
||||
# define QCA_EXPORT
|
||||
#define QCA_EXPORT
|
||||
#endif
|
||||
|
||||
// defs adapted qprocess_p.h
|
||||
@ -61,7 +61,6 @@ typedef int Q_PIPE_ID;
|
||||
|
||||
namespace QCA {
|
||||
|
||||
|
||||
/**
|
||||
\class QPipeDevice qpipe.h QtCrypto
|
||||
|
||||
@ -74,136 +73,136 @@ namespace QCA {
|
||||
*/
|
||||
class QCA_EXPORT QPipeDevice : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
public:
|
||||
/**
|
||||
The type of device
|
||||
*/
|
||||
enum Type
|
||||
{
|
||||
Read, ///< The pipe end can be read from
|
||||
Write ///< The pipe end can be written to
|
||||
};
|
||||
/**
|
||||
The type of device
|
||||
*/
|
||||
enum Type
|
||||
{
|
||||
Read, ///< The pipe end can be read from
|
||||
Write ///< The pipe end can be written to
|
||||
};
|
||||
|
||||
/**
|
||||
Standard constructor
|
||||
/**
|
||||
Standard constructor
|
||||
|
||||
\param parent the parent object to this object
|
||||
*/
|
||||
QPipeDevice(QObject *parent = 0);
|
||||
~QPipeDevice();
|
||||
\param parent the parent object to this object
|
||||
*/
|
||||
QPipeDevice(QObject *parent = nullptr);
|
||||
~QPipeDevice() override;
|
||||
|
||||
/**
|
||||
The Type of the pipe device (that is, read or write)
|
||||
*/
|
||||
Type type() const;
|
||||
/**
|
||||
The Type of the pipe device (that is, read or write)
|
||||
*/
|
||||
Type type() const;
|
||||
|
||||
/**
|
||||
Test whether this object corresponds to a valid pipe
|
||||
*/
|
||||
bool isValid() const;
|
||||
/**
|
||||
Test whether this object corresponds to a valid pipe
|
||||
*/
|
||||
bool isValid() const;
|
||||
|
||||
/**
|
||||
The low level identification for this pipe.
|
||||
/**
|
||||
The low level identification for this pipe.
|
||||
|
||||
On Windows, this is a HANDLE. On Unix, this is a file descriptor (i.e. integer).
|
||||
On Windows, this is a HANDLE. On Unix, this is a file descriptor (i.e. integer).
|
||||
|
||||
Code using this method should be carefully tested for portability.
|
||||
Code using this method should be carefully tested for portability.
|
||||
|
||||
\sa idAsInt
|
||||
*/
|
||||
Q_PIPE_ID id() const;
|
||||
\sa idAsInt
|
||||
*/
|
||||
Q_PIPE_ID id() const;
|
||||
|
||||
/**
|
||||
The low level identification for this pipe, returned as an integer.
|
||||
/**
|
||||
The low level identification for this pipe, returned as an integer.
|
||||
|
||||
Code using this method should be carefully tested for portability.
|
||||
Code using this method should be carefully tested for portability.
|
||||
|
||||
\sa id().
|
||||
*/
|
||||
int idAsInt() const;
|
||||
\sa id().
|
||||
*/
|
||||
int idAsInt() const;
|
||||
|
||||
/**
|
||||
Take over an existing pipe id, closing the old pipe if any.
|
||||
/**
|
||||
Take over an existing pipe id, closing the old pipe if any.
|
||||
|
||||
\param id the identification of the pipe end to take over.
|
||||
\param t the type of pipe end (read or write).
|
||||
*/
|
||||
void take(Q_PIPE_ID id, Type t);
|
||||
\param id the identification of the pipe end to take over.
|
||||
\param t the type of pipe end (read or write).
|
||||
*/
|
||||
void take(Q_PIPE_ID id, Type t);
|
||||
|
||||
/**
|
||||
Enable the pipe for reading or writing (depending on Type)
|
||||
*/
|
||||
void enable();
|
||||
/**
|
||||
Enable the pipe for reading or writing (depending on Type)
|
||||
*/
|
||||
void enable();
|
||||
|
||||
/**
|
||||
Close the pipe end.
|
||||
*/
|
||||
void close();
|
||||
/**
|
||||
Close the pipe end.
|
||||
*/
|
||||
void close();
|
||||
|
||||
/**
|
||||
Release the pipe end, but do not close it.
|
||||
*/
|
||||
void release();
|
||||
/**
|
||||
Release the pipe end, but do not close it.
|
||||
*/
|
||||
void release();
|
||||
|
||||
/**
|
||||
Set the pipe end to be inheritable
|
||||
/**
|
||||
Set the pipe end to be inheritable
|
||||
|
||||
\note On Windows, this operation changes the pipe end id value.
|
||||
\note On Windows, this operation changes the pipe end id value.
|
||||
|
||||
\param enabled whether the pipe is inheritable (true) or not (false)
|
||||
*/
|
||||
bool setInheritable(bool enabled);
|
||||
\param enabled whether the pipe is inheritable (true) or not (false)
|
||||
*/
|
||||
bool setInheritable(bool enabled);
|
||||
|
||||
/**
|
||||
Obtain the number of bytes available to be read.
|
||||
*/
|
||||
int bytesAvailable() const;
|
||||
/**
|
||||
Obtain the number of bytes available to be read.
|
||||
*/
|
||||
int bytesAvailable() const;
|
||||
|
||||
/**
|
||||
Read from the pipe end
|
||||
/**
|
||||
Read from the pipe end
|
||||
|
||||
\param data where to put the data that has been read
|
||||
\param maxsize the maximum number of bytes to be read.
|
||||
\param data where to put the data that has been read
|
||||
\param maxsize the maximum number of bytes to be read.
|
||||
|
||||
\return the actual number of bytes read, 0 on end-of-file, or -1 on error.
|
||||
*/
|
||||
int read(char *data, int maxsize);
|
||||
\return the actual number of bytes read, 0 on end-of-file, or -1 on error.
|
||||
*/
|
||||
int read(char *data, int maxsize);
|
||||
|
||||
/**
|
||||
Write to the pipe end.
|
||||
/**
|
||||
Write to the pipe end.
|
||||
|
||||
\param data the source of the data to be written
|
||||
\param size the number of bytes in the data to be written
|
||||
\param data the source of the data to be written
|
||||
\param size the number of bytes in the data to be written
|
||||
|
||||
\note the data source must remain valid
|
||||
\note the data source must remain valid
|
||||
|
||||
\return the number of bytes written, or -1 on error.
|
||||
*/
|
||||
int write(const char *data, int size);
|
||||
\return the number of bytes written, or -1 on error.
|
||||
*/
|
||||
int write(const char *data, int size);
|
||||
|
||||
/**
|
||||
The result of a write operation
|
||||
/**
|
||||
The result of a write operation
|
||||
|
||||
\param written if not null, this will be set to the number of
|
||||
bytes written in the last operation.
|
||||
\param written if not null, this will be set to the number of
|
||||
bytes written in the last operation.
|
||||
|
||||
\return 0 on success (all data written), or -1 on error
|
||||
*/
|
||||
int writeResult(int *written) const;
|
||||
\return 0 on success (all data written), or -1 on error
|
||||
*/
|
||||
int writeResult(int *written) const;
|
||||
|
||||
Q_SIGNALS:
|
||||
/**
|
||||
Emitted when the pipe end can be read from or written to (depending on its Type).
|
||||
*/
|
||||
void notify();
|
||||
/**
|
||||
Emitted when the pipe end can be read from or written to (depending on its Type).
|
||||
*/
|
||||
void notify();
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(QPipeDevice)
|
||||
Q_DISABLE_COPY(QPipeDevice)
|
||||
|
||||
class Private;
|
||||
friend class Private;
|
||||
Private *d;
|
||||
class Private;
|
||||
friend class Private;
|
||||
Private *d;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -217,248 +216,247 @@ private:
|
||||
*/
|
||||
class QCA_EXPORT QPipeEnd : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
public:
|
||||
/**
|
||||
The type of error
|
||||
*/
|
||||
enum Error
|
||||
{
|
||||
ErrorEOF, ///< End of file error
|
||||
ErrorBroken ///< Broken pipe error
|
||||
};
|
||||
|
||||
/**
|
||||
The type of error
|
||||
*/
|
||||
enum Error
|
||||
{
|
||||
ErrorEOF, ///< End of file error
|
||||
ErrorBroken ///< Broken pipe error
|
||||
};
|
||||
/**
|
||||
Standard constructor
|
||||
|
||||
/**
|
||||
Standard constructor
|
||||
\param parent the parent object for this object
|
||||
*/
|
||||
QPipeEnd(QObject *parent = nullptr);
|
||||
|
||||
\param parent the parent object for this object
|
||||
*/
|
||||
QPipeEnd(QObject *parent = 0);
|
||||
~QPipeEnd() override;
|
||||
|
||||
~QPipeEnd();
|
||||
/**
|
||||
Reset the pipe end to an inactive state
|
||||
*/
|
||||
void reset();
|
||||
|
||||
/**
|
||||
Reset the pipe end to an inactive state
|
||||
*/
|
||||
void reset();
|
||||
/**
|
||||
The type of pipe end (either read or write)
|
||||
*/
|
||||
QPipeDevice::Type type() const;
|
||||
|
||||
/**
|
||||
The type of pipe end (either read or write)
|
||||
*/
|
||||
QPipeDevice::Type type() const;
|
||||
/**
|
||||
Determine whether the pipe end is valid.
|
||||
|
||||
/**
|
||||
Determine whether the pipe end is valid.
|
||||
\note This does not mean the pipe is ready to be used - you
|
||||
may need to call enable() first
|
||||
*/
|
||||
bool isValid() const;
|
||||
|
||||
\note This does not mean the pipe is ready to be used - you
|
||||
may need to call enable() first
|
||||
*/
|
||||
bool isValid() const;
|
||||
/**
|
||||
Pipe identification
|
||||
*/
|
||||
Q_PIPE_ID id() const;
|
||||
|
||||
/**
|
||||
Pipe identification
|
||||
*/
|
||||
Q_PIPE_ID id() const;
|
||||
/**
|
||||
Pipe identification
|
||||
*/
|
||||
int idAsInt() const;
|
||||
|
||||
/**
|
||||
Pipe identification
|
||||
*/
|
||||
int idAsInt() const;
|
||||
/**
|
||||
Take over an existing pipe handle
|
||||
|
||||
/**
|
||||
Take over an existing pipe handle
|
||||
|
||||
\param id the pipe handle
|
||||
\param t the type of the pipe (read or write)
|
||||
*/
|
||||
void take(Q_PIPE_ID id, QPipeDevice::Type t);
|
||||
\param id the pipe handle
|
||||
\param t the type of the pipe (read or write)
|
||||
*/
|
||||
void take(Q_PIPE_ID id, QPipeDevice::Type t);
|
||||
|
||||
#ifdef QPIPE_SECURE
|
||||
/**
|
||||
Sets whether the pipe uses secure memory for read/write
|
||||
/**
|
||||
Sets whether the pipe uses secure memory for read/write
|
||||
|
||||
Enabling this may reduce performance, and it should only be used if
|
||||
sensitive data is being transmitted (such as a passphrase).
|
||||
Enabling this may reduce performance, and it should only be used if
|
||||
sensitive data is being transmitted (such as a passphrase).
|
||||
|
||||
\param secure whether the pipe uses secure memory (true) or not (false).
|
||||
*/
|
||||
void setSecurityEnabled(bool secure);
|
||||
\param secure whether the pipe uses secure memory (true) or not (false).
|
||||
*/
|
||||
void setSecurityEnabled(bool secure);
|
||||
#endif
|
||||
|
||||
/**
|
||||
Enable the endpoint for the pipe
|
||||
/**
|
||||
Enable the endpoint for the pipe
|
||||
|
||||
When an endpoint is created, it is not
|
||||
able to be used until it is enabled.
|
||||
*/
|
||||
void enable();
|
||||
When an endpoint is created, it is not
|
||||
able to be used until it is enabled.
|
||||
*/
|
||||
void enable();
|
||||
|
||||
/**
|
||||
Close the end of the pipe
|
||||
/**
|
||||
Close the end of the pipe
|
||||
|
||||
\sa closed()
|
||||
*/
|
||||
void close();
|
||||
\sa closed()
|
||||
*/
|
||||
void close();
|
||||
|
||||
/**
|
||||
Let go of the active pipe handle, but don't close it
|
||||
/**
|
||||
Let go of the active pipe handle, but don't close it
|
||||
|
||||
Use this before destructing QPipeEnd, if you don't want the pipe
|
||||
to automatically close.
|
||||
*/
|
||||
void release();
|
||||
Use this before destructing QPipeEnd, if you don't want the pipe
|
||||
to automatically close.
|
||||
*/
|
||||
void release();
|
||||
|
||||
/**
|
||||
Sets whether the pipe should be inheritable to child processes
|
||||
/**
|
||||
Sets whether the pipe should be inheritable to child processes
|
||||
|
||||
Returns true if inheritability was successfully changed, otherwise
|
||||
false.
|
||||
Returns true if inheritability was successfully changed, otherwise
|
||||
false.
|
||||
|
||||
\param enabled whether the pipe is inheritable (true) or not (false).
|
||||
*/
|
||||
bool setInheritable(bool enabled);
|
||||
\param enabled whether the pipe is inheritable (true) or not (false).
|
||||
*/
|
||||
bool setInheritable(bool enabled);
|
||||
|
||||
/**
|
||||
Clear the contents of the pipe, and invalidate the pipe
|
||||
*/
|
||||
void finalize();
|
||||
/**
|
||||
Clear the contents of the pipe, and invalidate the pipe
|
||||
*/
|
||||
void finalize();
|
||||
|
||||
/**
|
||||
Clear the contents of the pipe, and release the pipe
|
||||
*/
|
||||
void finalizeAndRelease();
|
||||
/**
|
||||
Clear the contents of the pipe, and release the pipe
|
||||
*/
|
||||
void finalizeAndRelease();
|
||||
|
||||
/**
|
||||
Determine how many bytes are available to be read.
|
||||
/**
|
||||
Determine how many bytes are available to be read.
|
||||
|
||||
This only makes sense at the read end of the pipe
|
||||
This only makes sense at the read end of the pipe
|
||||
|
||||
\sa readyRead() for a signal that can be used to determine
|
||||
when there are bytes available to read.
|
||||
*/
|
||||
int bytesAvailable() const;
|
||||
\sa readyRead() for a signal that can be used to determine
|
||||
when there are bytes available to read.
|
||||
*/
|
||||
int bytesAvailable() const;
|
||||
|
||||
/**
|
||||
Returns the number of bytes pending to write
|
||||
/**
|
||||
Returns the number of bytes pending to write
|
||||
|
||||
This only makes sense at the write end of the pipe
|
||||
This only makes sense at the write end of the pipe
|
||||
|
||||
\sa bytesWritten() for a signal that can be used to determine
|
||||
when bytes have been written
|
||||
*/
|
||||
int bytesToWrite() const;
|
||||
\sa bytesWritten() for a signal that can be used to determine
|
||||
when bytes have been written
|
||||
*/
|
||||
int bytesToWrite() const;
|
||||
|
||||
/**
|
||||
Read bytes from the pipe.
|
||||
/**
|
||||
Read bytes from the pipe.
|
||||
|
||||
You can only call this on the read end of the pipe
|
||||
You can only call this on the read end of the pipe
|
||||
|
||||
If the pipe is using secure memory, you should use readSecure()
|
||||
If the pipe is using secure memory, you should use readSecure()
|
||||
|
||||
\param bytes the number of bytes to read (-1 for all
|
||||
content).
|
||||
*/
|
||||
QByteArray read(int bytes = -1);
|
||||
\param bytes the number of bytes to read (-1 for all
|
||||
content).
|
||||
*/
|
||||
QByteArray read(int bytes = -1);
|
||||
|
||||
/**
|
||||
Write bytes to the pipe.
|
||||
/**
|
||||
Write bytes to the pipe.
|
||||
|
||||
You can only call this on the write end of the pipe.
|
||||
You can only call this on the write end of the pipe.
|
||||
|
||||
If the pipe is using secure memory, you should use writeSecure().
|
||||
If the pipe is using secure memory, you should use writeSecure().
|
||||
|
||||
\param a the array to write to the pipe
|
||||
*/
|
||||
void write(const QByteArray &a);
|
||||
\param a the array to write to the pipe
|
||||
*/
|
||||
void write(const QByteArray &a);
|
||||
|
||||
#ifdef QPIPE_SECURE
|
||||
/**
|
||||
Read bytes from the pipe.
|
||||
/**
|
||||
Read bytes from the pipe.
|
||||
|
||||
You can only call this on the read end of the pipe
|
||||
You can only call this on the read end of the pipe
|
||||
|
||||
If the pipe is using insecure memory, you should use read()
|
||||
If the pipe is using insecure memory, you should use read()
|
||||
|
||||
\param bytes the number of bytes to read (-1 for all
|
||||
content).
|
||||
*/
|
||||
SecureArray readSecure(int bytes = -1);
|
||||
\param bytes the number of bytes to read (-1 for all
|
||||
content).
|
||||
*/
|
||||
SecureArray readSecure(int bytes = -1);
|
||||
|
||||
/**
|
||||
Write bytes to the pipe.
|
||||
/**
|
||||
Write bytes to the pipe.
|
||||
|
||||
You can only call this on the write end of the pipe.
|
||||
You can only call this on the write end of the pipe.
|
||||
|
||||
If the pipe is using insecure memory, you should use write().
|
||||
If the pipe is using insecure memory, you should use write().
|
||||
|
||||
\param a the array to write to the pipe
|
||||
*/
|
||||
void writeSecure(const SecureArray &a);
|
||||
\param a the array to write to the pipe
|
||||
*/
|
||||
void writeSecure(const SecureArray &a);
|
||||
#endif
|
||||
|
||||
/**
|
||||
Returns any unsent bytes queued for writing
|
||||
/**
|
||||
Returns any unsent bytes queued for writing
|
||||
|
||||
If the pipe is using secure memory, you should use
|
||||
takeBytesToWriteSecure().
|
||||
*/
|
||||
QByteArray takeBytesToWrite();
|
||||
If the pipe is using secure memory, you should use
|
||||
takeBytesToWriteSecure().
|
||||
*/
|
||||
QByteArray takeBytesToWrite();
|
||||
|
||||
#ifdef QPIPE_SECURE
|
||||
/**
|
||||
Returns any unsent bytes queued for writing
|
||||
/**
|
||||
Returns any unsent bytes queued for writing
|
||||
|
||||
If the pipe is using insecure memory, you should use
|
||||
takeBytesToWrite().
|
||||
*/
|
||||
SecureArray takeBytesToWriteSecure();
|
||||
If the pipe is using insecure memory, you should use
|
||||
takeBytesToWrite().
|
||||
*/
|
||||
SecureArray takeBytesToWriteSecure();
|
||||
#endif
|
||||
|
||||
Q_SIGNALS:
|
||||
/**
|
||||
Emitted when there are bytes available to be read
|
||||
from the read end of the pipe.
|
||||
/**
|
||||
Emitted when there are bytes available to be read
|
||||
from the read end of the pipe.
|
||||
|
||||
\sa bytesAvailable()
|
||||
*/
|
||||
void readyRead();
|
||||
\sa bytesAvailable()
|
||||
*/
|
||||
void readyRead();
|
||||
|
||||
/**
|
||||
Emitted when bytes have been written to the
|
||||
write end of the pipe.
|
||||
/**
|
||||
Emitted when bytes have been written to the
|
||||
write end of the pipe.
|
||||
|
||||
\param bytes the number of bytes written
|
||||
*/
|
||||
void bytesWritten(int bytes);
|
||||
\param bytes the number of bytes written
|
||||
*/
|
||||
void bytesWritten(int bytes);
|
||||
|
||||
/**
|
||||
Emitted when this end of the pipe is closed as a result of calling
|
||||
close()
|
||||
/**
|
||||
Emitted when this end of the pipe is closed as a result of calling
|
||||
close()
|
||||
|
||||
If this is the write end of the pipe and there is data still
|
||||
pending to write, this signal will be emitted once all of the data
|
||||
has been written.
|
||||
If this is the write end of the pipe and there is data still
|
||||
pending to write, this signal will be emitted once all of the data
|
||||
has been written.
|
||||
|
||||
To be notified if the other end of the pipe has been closed, see
|
||||
error().
|
||||
*/
|
||||
void closed();
|
||||
To be notified if the other end of the pipe has been closed, see
|
||||
error().
|
||||
*/
|
||||
void closed();
|
||||
|
||||
/**
|
||||
Emitted when the pipe encounters an error trying to read or write,
|
||||
or if the other end of the pipe has been closed
|
||||
/**
|
||||
Emitted when the pipe encounters an error trying to read or write,
|
||||
or if the other end of the pipe has been closed
|
||||
|
||||
\param e the reason for error
|
||||
*/
|
||||
void error(QCA::QPipeEnd::Error e);
|
||||
\param e the reason for error
|
||||
*/
|
||||
void error(QCA::QPipeEnd::Error e);
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(QPipeEnd)
|
||||
Q_DISABLE_COPY(QPipeEnd)
|
||||
|
||||
class Private;
|
||||
friend class Private;
|
||||
Private *d;
|
||||
class Private;
|
||||
friend class Private;
|
||||
Private *d;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -480,53 +478,59 @@ private:
|
||||
class QCA_EXPORT QPipe
|
||||
{
|
||||
public:
|
||||
/**
|
||||
Standard constructor
|
||||
/**
|
||||
Standard constructor
|
||||
|
||||
\note You must call create() before using the pipe ends.
|
||||
\note You must call create() before using the pipe ends.
|
||||
|
||||
\param parent the parent object for this object
|
||||
*/
|
||||
QPipe(QObject *parent = 0);
|
||||
\param parent the parent object for this object
|
||||
*/
|
||||
QPipe(QObject *parent = nullptr);
|
||||
|
||||
~QPipe();
|
||||
~QPipe();
|
||||
|
||||
/**
|
||||
Reset the pipe.
|
||||
/**
|
||||
Reset the pipe.
|
||||
|
||||
At this point, the readEnd() and writeEnd() calls
|
||||
will no longer be valid.
|
||||
*/
|
||||
void reset();
|
||||
At this point, the readEnd() and writeEnd() calls
|
||||
will no longer be valid.
|
||||
*/
|
||||
void reset();
|
||||
|
||||
#ifdef QPIPE_SECURE
|
||||
/**
|
||||
Create the pipe
|
||||
/**
|
||||
Create the pipe
|
||||
|
||||
\param secure whether to use secure memory (true) or not (false)
|
||||
*/
|
||||
bool create(bool secure = false);
|
||||
\param secure whether to use secure memory (true) or not (false)
|
||||
*/
|
||||
bool create(bool secure = false);
|
||||
#else
|
||||
/**
|
||||
Create the pipe
|
||||
*/
|
||||
bool create();
|
||||
/**
|
||||
Create the pipe
|
||||
*/
|
||||
bool create();
|
||||
#endif
|
||||
|
||||
/**
|
||||
The read end of the pipe.
|
||||
*/
|
||||
QPipeEnd & readEnd() { return i; }
|
||||
/**
|
||||
The read end of the pipe.
|
||||
*/
|
||||
QPipeEnd &readEnd()
|
||||
{
|
||||
return i;
|
||||
}
|
||||
|
||||
/**
|
||||
The write end of the pipe.
|
||||
*/
|
||||
QPipeEnd & writeEnd() { return o; }
|
||||
/**
|
||||
The write end of the pipe.
|
||||
*/
|
||||
QPipeEnd &writeEnd()
|
||||
{
|
||||
return o;
|
||||
}
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(QPipe)
|
||||
Q_DISABLE_COPY(QPipe)
|
||||
|
||||
QPipeEnd i, o;
|
||||
QPipeEnd i, o;
|
||||
};
|
||||
|
||||
}
|
||||
|
40
metainfo.yaml
Normal file
40
metainfo.yaml
Normal 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
|
@ -22,36 +22,36 @@ if(NOT_PLUGIN_LIST)
|
||||
set(WITH_${PLUGIN}_PLUGIN "yes")
|
||||
elseif("${BUILD_PLUGINS}" STREQUAL "auto")
|
||||
set(WITH_${PLUGIN}_PLUGIN "auto")
|
||||
else("${BUILD_PLUGINS}" STREQUAL "all")
|
||||
else()
|
||||
set(WITH_${PLUGIN}_PLUGIN "no")
|
||||
endif("${BUILD_PLUGINS}" STREQUAL "all")
|
||||
endif()
|
||||
elseif(NOT WITH_${PLUGIN}_PLUGIN)
|
||||
set(WITH_${PLUGIN}_PLUGIN "no")
|
||||
elseif("${WITH_${PLUGIN}_PLUGIN}" STREQUAL "auto")
|
||||
set(WITH_${PLUGIN}_PLUGIN "auto")
|
||||
else("${WITH_${PLUGIN}_PLUGIN}" STREQUAL "")
|
||||
else()
|
||||
set(WITH_${PLUGIN}_PLUGIN "yes")
|
||||
endif("${WITH_${PLUGIN}_PLUGIN}" STREQUAL "")
|
||||
endif()
|
||||
|
||||
# Build plugin if yes or auto
|
||||
if(WITH_${PLUGIN}_PLUGIN)
|
||||
add_subdirectory("qca-${PLUGIN}")
|
||||
else(WITH_${PLUGIN}_PLUGIN)
|
||||
else()
|
||||
disable_plugin(${PLUGIN})
|
||||
endif(WITH_${PLUGIN}_PLUGIN)
|
||||
endif()
|
||||
endforeach(PLUGIN IN LISTS PLUGINS)
|
||||
else(NOT_PLUGIN_LIST)
|
||||
else()
|
||||
# BUILD_PLUGINS has list plugins to builds
|
||||
foreach(PLUGIN IN LISTS PLUGINS)
|
||||
list(FIND BUILD_PLUGINS "${PLUGIN}" PLUGIN_INDEX)
|
||||
if(PLUGIN_INDEX GREATER -1)
|
||||
set(WITH_${PLUGIN}_PLUGIN "yes")
|
||||
add_subdirectory("qca-${PLUGIN}")
|
||||
else(PLUGIN_INDEX GREATER -1)
|
||||
else()
|
||||
disable_plugin(${PLUGIN})
|
||||
endif(PLUGIN_INDEX GREATER -1)
|
||||
endif()
|
||||
endforeach(PLUGIN IN LISTS PLUGINS)
|
||||
endif(NOT_PLUGIN_LIST)
|
||||
endif()
|
||||
|
||||
message("")
|
||||
message("Plugins:")
|
||||
|
@ -1,22 +1,25 @@
|
||||
find_package(PkgConfig REQUIRED)
|
||||
if(WITH_botan_PLUGIN STREQUAL "yes")
|
||||
find_package(Botan REQUIRED)
|
||||
else(WITH_botan_PLUGIN STREQUAL "yes")
|
||||
find_package(Botan)
|
||||
endif(WITH_botan_PLUGIN STREQUAL "yes")
|
||||
pkg_check_modules(BOTAN REQUIRED IMPORTED_TARGET botan-2)
|
||||
else()
|
||||
pkg_check_modules(BOTAN IMPORTED_TARGET botan-2)
|
||||
endif()
|
||||
|
||||
if(BOTAN_FOUND)
|
||||
enable_plugin("botan")
|
||||
|
||||
set(QCA_BOTAN_SOURCES qca-botan.cpp)
|
||||
add_definitions(${BOTAN_CFLAGS})
|
||||
my_automoc(QCA_BOTAN_SOURCES)
|
||||
add_library(qca-botan ${PLUGIN_TYPE} ${QCA_BOTAN_SOURCES})
|
||||
|
||||
if(APPLE AND ${PLUGIN_TYPE} STREQUAL "MODULE")
|
||||
set_property(TARGET qca-botan PROPERTY SUFFIX ".dylib")
|
||||
endif()
|
||||
|
||||
target_link_libraries(qca-botan ${QT_QTCORE_LIBRARY} ${QCA_LIB_NAME} ${BOTAN_LIBRARIES})
|
||||
if(QT6)
|
||||
target_link_libraries(qca-botan Qt6::Core ${QCA_LIB_NAME} PkgConfig::BOTAN)
|
||||
else()
|
||||
target_link_libraries(qca-botan Qt5::Core ${QCA_LIB_NAME} PkgConfig::BOTAN)
|
||||
endif()
|
||||
|
||||
if(NOT DEVELOPER_MODE)
|
||||
install(TARGETS qca-botan
|
||||
@ -27,6 +30,6 @@ if(BOTAN_FOUND)
|
||||
install_pdb(qca-botan ${QCA_CRYPTO_INSTALL_DIR})
|
||||
endif()
|
||||
|
||||
else(BOTAN_FOUND)
|
||||
else()
|
||||
disable_plugin("botan")
|
||||
endif(BOTAN_FOUND)
|
||||
endif()
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,22 +1,25 @@
|
||||
if(WITH_cyrus-sasl_PLUGIN STREQUAL "yes")
|
||||
find_package(Sasl2 REQUIRED)
|
||||
else(WITH_cyrus-sasl_PLUGIN STREQUAL "yes")
|
||||
else()
|
||||
find_package(Sasl2)
|
||||
endif(WITH_cyrus-sasl_PLUGIN STREQUAL "yes")
|
||||
endif()
|
||||
|
||||
if(SASL2_FOUND)
|
||||
enable_plugin("cyrus-sasl")
|
||||
|
||||
set(QCA_SASL_SOURCES qca-cyrus-sasl.cpp)
|
||||
include_directories( ${SASL2_INCLUDE_DIR} )
|
||||
my_automoc( QCA_SASL_SOURCES )
|
||||
add_library(qca-cyrus-sasl ${PLUGIN_TYPE} ${QCA_SASL_SOURCES})
|
||||
|
||||
if(APPLE AND ${PLUGIN_TYPE} STREQUAL "MODULE")
|
||||
set_property(TARGET qca-cyrus-sasl PROPERTY SUFFIX ".dylib")
|
||||
endif()
|
||||
|
||||
target_link_libraries(qca-cyrus-sasl ${QT_QTCORE_LIBRARY} ${QCA_LIB_NAME} ${SASL2_LIBRARIES})
|
||||
if(QT6)
|
||||
target_link_libraries(qca-cyrus-sasl Qt6::Core ${QCA_LIB_NAME} ${SASL2_LIBRARIES})
|
||||
else()
|
||||
target_link_libraries(qca-cyrus-sasl Qt5::Core ${QCA_LIB_NAME} ${SASL2_LIBRARIES})
|
||||
endif()
|
||||
|
||||
if(NOT DEVELOPER_MODE)
|
||||
install(TARGETS qca-cyrus-sasl
|
||||
@ -26,6 +29,6 @@ if(SASL2_FOUND)
|
||||
|
||||
install_pdb(qca-cyrus-sasl ${QCA_CRYPTO_INSTALL_DIR})
|
||||
endif()
|
||||
else(SASL2_FOUND)
|
||||
else()
|
||||
disable_plugin("cyrus-sasl")
|
||||
endif(SASL2_FOUND)
|
||||
endif()
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,8 +1,8 @@
|
||||
if(WITH_gcrypt_PLUGIN STREQUAL "yes")
|
||||
find_package(LibGcrypt REQUIRED)
|
||||
else(WITH_gcrypt_PLUGIN STREQUAL "yes")
|
||||
else()
|
||||
find_package(LibGcrypt)
|
||||
endif(WITH_gcrypt_PLUGIN STREQUAL "yes")
|
||||
endif()
|
||||
|
||||
if(LIBGCRYPT_FOUND)
|
||||
include(CheckTypeSize)
|
||||
@ -19,14 +19,17 @@ if(LIBGCRYPT_FOUND)
|
||||
|
||||
set(QCA_GCRYPT_SOURCES qca-gcrypt.cpp)
|
||||
add_definitions(${LIBGCRYPT_CFLAGS})
|
||||
my_automoc(QCA_GCRYPT_SOURCES)
|
||||
add_library(qca-gcrypt ${PLUGIN_TYPE} ${QCA_GCRYPT_SOURCES})
|
||||
|
||||
if(APPLE AND ${PLUGIN_TYPE} STREQUAL "MODULE")
|
||||
set_property(TARGET qca-gcrypt PROPERTY SUFFIX ".dylib")
|
||||
endif()
|
||||
|
||||
target_link_libraries(qca-gcrypt ${QT_QTCORE_LIBRARY} ${QCA_LIB_NAME} ${LIBGCRYPT_LIBRARIES})
|
||||
if(QT6)
|
||||
target_link_libraries(qca-gcrypt Qt6::Core ${QCA_LIB_NAME} ${LIBGCRYPT_LIBRARIES})
|
||||
else()
|
||||
target_link_libraries(qca-gcrypt Qt5::Core ${QCA_LIB_NAME} ${LIBGCRYPT_LIBRARIES})
|
||||
endif()
|
||||
|
||||
if(NOT DEVELOPER_MODE)
|
||||
install(TARGETS qca-gcrypt
|
||||
@ -36,10 +39,10 @@ if(LIBGCRYPT_FOUND)
|
||||
|
||||
install_pdb(qca-gcrypt ${QCA_CRYPTO_INSTALL_DIR})
|
||||
endif()
|
||||
else(HAVE_GCRY_ERROR_T)
|
||||
else()
|
||||
message(STATUS "libgcrypt seems to be too old")
|
||||
disable_plugin("gcrypt")
|
||||
endif(HAVE_GCRY_ERROR_T)
|
||||
else(LIBGCRYPT_FOUND)
|
||||
endif()
|
||||
else()
|
||||
disable_plugin("gcrypt")
|
||||
endif(LIBGCRYPT_FOUND)
|
||||
endif()
|
||||
|
120
plugins/qca-gcrypt/hkdf.c
Normal file
120
plugins/qca-gcrypt/hkdf.c
Normal 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;
|
||||
}
|
@ -45,153 +45,151 @@
|
||||
* Output: DK derived key, a dkLen-octet string
|
||||
*/
|
||||
|
||||
gcry_error_t
|
||||
gcry_pbkdf2 (int PRF, const char *P, size_t Plen, const char *S,
|
||||
size_t Slen, unsigned int c, unsigned int dkLen, char *DK)
|
||||
static gcry_error_t gcry_pbkdf2(int PRF,
|
||||
const char * P,
|
||||
size_t Plen,
|
||||
const char * S,
|
||||
size_t Slen,
|
||||
unsigned int c,
|
||||
unsigned int dkLen,
|
||||
char * DK)
|
||||
{
|
||||
gcry_md_hd_t prf;
|
||||
gcry_error_t rc;
|
||||
char *U;
|
||||
unsigned int u;
|
||||
unsigned int hLen;
|
||||
unsigned int l;
|
||||
unsigned int r;
|
||||
unsigned char *p;
|
||||
unsigned int i;
|
||||
unsigned int k;
|
||||
gcry_md_hd_t prf;
|
||||
gcry_error_t rc;
|
||||
char * U;
|
||||
unsigned int u;
|
||||
unsigned int hLen;
|
||||
unsigned int l;
|
||||
unsigned int r;
|
||||
unsigned char *p;
|
||||
unsigned int i;
|
||||
unsigned int k;
|
||||
|
||||
hLen = gcry_md_get_algo_dlen (PRF);
|
||||
if (hLen == 0)
|
||||
return GPG_ERR_UNSUPPORTED_ALGORITHM;
|
||||
hLen = gcry_md_get_algo_dlen(PRF);
|
||||
if (hLen == 0)
|
||||
return GPG_ERR_UNSUPPORTED_ALGORITHM;
|
||||
|
||||
if (c == 0)
|
||||
return GPG_ERR_INV_ARG;
|
||||
if (c == 0)
|
||||
return GPG_ERR_INV_ARG;
|
||||
|
||||
if (dkLen == 0)
|
||||
return GPG_ERR_TOO_SHORT;
|
||||
if (dkLen == 0)
|
||||
return GPG_ERR_TOO_SHORT;
|
||||
|
||||
/*
|
||||
*
|
||||
* Steps:
|
||||
*
|
||||
* 1. If dkLen > (2^32 - 1) * hLen, output "derived key too long" and
|
||||
* stop.
|
||||
*/
|
||||
/*
|
||||
*
|
||||
* Steps:
|
||||
*
|
||||
* 1. If dkLen > (2^32 - 1) * hLen, output "derived key too long" and
|
||||
* stop.
|
||||
*/
|
||||
|
||||
if (dkLen > 4294967295U)
|
||||
return GPG_ERR_TOO_LARGE;
|
||||
if (dkLen > 4294967295U)
|
||||
return GPG_ERR_TOO_LARGE;
|
||||
|
||||
/*
|
||||
* 2. Let l be the number of hLen-octet blocks in the derived key,
|
||||
* rounding up, and let r be the number of octets in the last
|
||||
* block:
|
||||
*
|
||||
* l = CEIL (dkLen / hLen) ,
|
||||
* r = dkLen - (l - 1) * hLen .
|
||||
*
|
||||
* Here, CEIL (x) is the "ceiling" function, i.e. the smallest
|
||||
* integer greater than, or equal to, x.
|
||||
*/
|
||||
/*
|
||||
* 2. Let l be the number of hLen-octet blocks in the derived key,
|
||||
* rounding up, and let r be the number of octets in the last
|
||||
* block:
|
||||
*
|
||||
* l = CEIL (dkLen / hLen) ,
|
||||
* r = dkLen - (l - 1) * hLen .
|
||||
*
|
||||
* Here, CEIL (x) is the "ceiling" function, i.e. the smallest
|
||||
* integer greater than, or equal to, x.
|
||||
*/
|
||||
|
||||
l = dkLen / hLen;
|
||||
if (dkLen % hLen)
|
||||
l++;
|
||||
r = dkLen - (l - 1) * hLen;
|
||||
l = dkLen / hLen;
|
||||
if (dkLen % hLen)
|
||||
l++;
|
||||
r = dkLen - (l - 1) * hLen;
|
||||
|
||||
/*
|
||||
* 3. For each block of the derived key apply the function F defined
|
||||
* below to the password P, the salt S, the iteration count c, and
|
||||
* the block index to compute the block:
|
||||
*
|
||||
* T_1 = F (P, S, c, 1) ,
|
||||
* T_2 = F (P, S, c, 2) ,
|
||||
* ...
|
||||
* T_l = F (P, S, c, l) ,
|
||||
*
|
||||
* where the function F is defined as the exclusive-or sum of the
|
||||
* first c iterates of the underlying pseudorandom function PRF
|
||||
* applied to the password P and the concatenation of the salt S
|
||||
* and the block index i:
|
||||
*
|
||||
* F (P, S, c, i) = U_1 \xor U_2 \xor ... \xor U_c
|
||||
*
|
||||
* where
|
||||
*
|
||||
* U_1 = PRF (P, S || INT (i)) ,
|
||||
* U_2 = PRF (P, U_1) ,
|
||||
* ...
|
||||
* U_c = PRF (P, U_{c-1}) .
|
||||
*
|
||||
* Here, INT (i) is a four-octet encoding of the integer i, most
|
||||
* significant octet first.
|
||||
*
|
||||
* 4. Concatenate the blocks and extract the first dkLen octets to
|
||||
* produce a derived key DK:
|
||||
*
|
||||
* DK = T_1 || T_2 || ... || T_l<0..r-1>
|
||||
*
|
||||
* 5. Output the derived key DK.
|
||||
*
|
||||
* Note. The construction of the function F follows a "belt-and-
|
||||
* suspenders" approach. The iterates U_i are computed recursively to
|
||||
* remove a degree of parallelism from an opponent; they are exclusive-
|
||||
* ored together to reduce concerns about the recursion degenerating
|
||||
* into a small set of values.
|
||||
*
|
||||
*/
|
||||
rc = gcry_md_open (&prf, PRF, GCRY_MD_FLAG_HMAC | GCRY_MD_FLAG_SECURE);
|
||||
if (rc != GPG_ERR_NO_ERROR)
|
||||
/*
|
||||
* 3. For each block of the derived key apply the function F defined
|
||||
* below to the password P, the salt S, the iteration count c, and
|
||||
* the block index to compute the block:
|
||||
*
|
||||
* T_1 = F (P, S, c, 1) ,
|
||||
* T_2 = F (P, S, c, 2) ,
|
||||
* ...
|
||||
* T_l = F (P, S, c, l) ,
|
||||
*
|
||||
* where the function F is defined as the exclusive-or sum of the
|
||||
* first c iterates of the underlying pseudorandom function PRF
|
||||
* applied to the password P and the concatenation of the salt S
|
||||
* and the block index i:
|
||||
*
|
||||
* F (P, S, c, i) = U_1 \xor U_2 \xor ... \xor U_c
|
||||
*
|
||||
* where
|
||||
*
|
||||
* U_1 = PRF (P, S || INT (i)) ,
|
||||
* U_2 = PRF (P, U_1) ,
|
||||
* ...
|
||||
* U_c = PRF (P, U_{c-1}) .
|
||||
*
|
||||
* Here, INT (i) is a four-octet encoding of the integer i, most
|
||||
* significant octet first.
|
||||
*
|
||||
* 4. Concatenate the blocks and extract the first dkLen octets to
|
||||
* produce a derived key DK:
|
||||
*
|
||||
* DK = T_1 || T_2 || ... || T_l<0..r-1>
|
||||
*
|
||||
* 5. Output the derived key DK.
|
||||
*
|
||||
* Note. The construction of the function F follows a "belt-and-
|
||||
* suspenders" approach. The iterates U_i are computed recursively to
|
||||
* remove a degree of parallelism from an opponent; they are exclusive-
|
||||
* ored together to reduce concerns about the recursion degenerating
|
||||
* into a small set of values.
|
||||
*
|
||||
*/
|
||||
rc = gcry_md_open(&prf, PRF, GCRY_MD_FLAG_HMAC | GCRY_MD_FLAG_SECURE);
|
||||
if (rc != GPG_ERR_NO_ERROR)
|
||||
return rc;
|
||||
|
||||
U = (char *)gcry_malloc(hLen);
|
||||
if (!U) {
|
||||
rc = GPG_ERR_ENOMEM;
|
||||
goto done;
|
||||
}
|
||||
|
||||
for (i = 1; i <= l; i++) {
|
||||
memset(DK + (i - 1) * hLen, 0, i == l ? r : hLen);
|
||||
|
||||
for (u = 1; u <= c; u++) {
|
||||
gcry_md_reset(prf);
|
||||
|
||||
rc = gcry_md_setkey(prf, P, Plen);
|
||||
if (rc != GPG_ERR_NO_ERROR) {
|
||||
goto done;
|
||||
}
|
||||
if (u == 1) {
|
||||
char tmp[4];
|
||||
gcry_md_write(prf, S, Slen);
|
||||
tmp[0] = (i & 0xff000000) >> 24;
|
||||
tmp[1] = (i & 0x00ff0000) >> 16;
|
||||
tmp[2] = (i & 0x0000ff00) >> 8;
|
||||
tmp[3] = (i & 0x000000ff) >> 0;
|
||||
gcry_md_write(prf, tmp, 4);
|
||||
} else
|
||||
gcry_md_write(prf, U, hLen);
|
||||
|
||||
p = gcry_md_read(prf, PRF);
|
||||
if (p == nullptr) {
|
||||
rc = GPG_ERR_CONFIGURATION;
|
||||
goto done;
|
||||
}
|
||||
|
||||
memcpy(U, p, hLen);
|
||||
for (k = 0; k < (i == l ? r : hLen); k++)
|
||||
DK[(i - 1) * hLen + k] ^= U[k];
|
||||
}
|
||||
}
|
||||
|
||||
rc = GPG_ERR_NO_ERROR;
|
||||
done:
|
||||
gcry_md_close(prf);
|
||||
gcry_free(U);
|
||||
return rc;
|
||||
|
||||
U = (char*)gcry_malloc(hLen);
|
||||
if (!U)
|
||||
{
|
||||
rc = GPG_ERR_ENOMEM;
|
||||
goto done;
|
||||
}
|
||||
|
||||
for (i = 1; i <= l; i++)
|
||||
{
|
||||
memset(DK + (i - 1) * hLen, 0, i == l ? r : hLen);
|
||||
|
||||
for (u = 1; u <= c; u++)
|
||||
{
|
||||
gcry_md_reset (prf);
|
||||
|
||||
rc = gcry_md_setkey (prf, P, Plen);
|
||||
if (rc != GPG_ERR_NO_ERROR) {
|
||||
goto done;
|
||||
}
|
||||
if (u == 1)
|
||||
{
|
||||
char tmp[4];
|
||||
gcry_md_write (prf, S, Slen);
|
||||
tmp[0] = (i & 0xff000000) >> 24;
|
||||
tmp[1] = (i & 0x00ff0000) >> 16;
|
||||
tmp[2] = (i & 0x0000ff00) >> 8;
|
||||
tmp[3] = (i & 0x000000ff) >> 0;
|
||||
gcry_md_write (prf, tmp, 4);
|
||||
}
|
||||
else
|
||||
gcry_md_write (prf, U, hLen);
|
||||
|
||||
p = gcry_md_read (prf, PRF);
|
||||
if (p == NULL)
|
||||
{
|
||||
rc = GPG_ERR_CONFIGURATION;
|
||||
goto done;
|
||||
}
|
||||
|
||||
memcpy (U, p, hLen);
|
||||
for (k = 0; k < (i == l ? r : hLen); k++)
|
||||
DK[(i - 1) * hLen + k] ^= U[k];
|
||||
}
|
||||
}
|
||||
|
||||
rc = GPG_ERR_NO_ERROR;
|
||||
done:
|
||||
gcry_md_close (prf);
|
||||
gcry_free(U);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -2,11 +2,8 @@
|
||||
|
||||
enable_plugin("gnupg")
|
||||
|
||||
set(QCA_GNUPG_MOC_SOURCES
|
||||
set(QCA_GNUPG_SOURCES
|
||||
qca-gnupg.cpp
|
||||
)
|
||||
|
||||
set(QCA_GNUPG_NONMOC_SOURCES
|
||||
gpgop.cpp
|
||||
utils.cpp
|
||||
gpgproc/sprocess.cpp
|
||||
@ -21,30 +18,39 @@ set(QCA_GNUPG_NONMOC_SOURCES
|
||||
gpgproc/gpgproc.cpp
|
||||
)
|
||||
|
||||
my_automoc(QCA_GNUPG_MOC_SOURCES)
|
||||
set(QCA_GNUPG_HEADERS
|
||||
gpgaction.h
|
||||
ringwatch.h
|
||||
gpgop.h
|
||||
gpgop_p.h
|
||||
lineconverter.h
|
||||
mypgpkeycontext.h
|
||||
mykeystoreentry.h
|
||||
mykeystorelist.h
|
||||
gpgproc/gpgproc_p.h
|
||||
gpgproc/sprocess.h
|
||||
gpgproc/gpgproc.h
|
||||
utils.h
|
||||
mymessagecontext.h
|
||||
myopenpgpcontext.h
|
||||
)
|
||||
|
||||
qt4_wrap_cpp(EXTRA_GNUPG_SOURCES gpgop.h)
|
||||
qt4_wrap_cpp(EXTRA_GNUPG_SOURCES gpgop_p.h)
|
||||
qt4_wrap_cpp(EXTRA_GNUPG_SOURCES gpgproc/gpgproc.h)
|
||||
qt4_wrap_cpp(EXTRA_GNUPG_SOURCES gpgproc/gpgproc_p.h)
|
||||
qt4_wrap_cpp(EXTRA_GNUPG_SOURCES gpgproc/sprocess.h)
|
||||
qt4_wrap_cpp(EXTRA_GNUPG_SOURCES ringwatch.h)
|
||||
qt4_wrap_cpp(EXTRA_GNUPG_SOURCES mykeystorelist.h)
|
||||
qt4_wrap_cpp(EXTRA_GNUPG_SOURCES mymessagecontext.h)
|
||||
qt4_wrap_cpp(EXTRA_GNUPG_SOURCES gpgaction.h)
|
||||
|
||||
add_library(qca-gnupg ${PLUGIN_TYPE} ${QCA_GNUPG_MOC_SOURCES} ${QCA_GNUPG_NONMOC_SOURCES} ${EXTRA_GNUPG_SOURCES})
|
||||
add_library(qca-gnupg ${PLUGIN_TYPE} ${QCA_GNUPG_SOURCES} ${EXTRA_GNUPG_SOURCES} ${QCA_GNUPG_HEADERS})
|
||||
|
||||
if(APPLE AND ${PLUGIN_TYPE} STREQUAL "MODULE")
|
||||
set_property(TARGET qca-gnupg PROPERTY SUFFIX ".dylib")
|
||||
endif()
|
||||
|
||||
include_directories(gpgproc)
|
||||
target_link_libraries(qca-gnupg ${QT_QTCORE_LIBRARY} ${QCA_LIB_NAME})
|
||||
if(QT6)
|
||||
target_link_libraries(qca-gnupg Qt6::Core ${QCA_LIB_NAME})
|
||||
else()
|
||||
target_link_libraries(qca-gnupg Qt5::Core ${QCA_LIB_NAME})
|
||||
endif()
|
||||
|
||||
if (WIN32)
|
||||
target_link_libraries(qca-gnupg advapi32)
|
||||
endif (WIN32)
|
||||
endif()
|
||||
|
||||
if(NOT DEVELOPER_MODE)
|
||||
install(TARGETS qca-gnupg DESTINATION
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -19,13 +19,13 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "lineconverter.h"
|
||||
#include "qca_safetimer.h"
|
||||
#include "gpgop.h"
|
||||
#include "gpgproc.h"
|
||||
#include "lineconverter.h"
|
||||
#include "qca_safetimer.h"
|
||||
#include <QByteArray>
|
||||
#include <QObject>
|
||||
#include <QStringList>
|
||||
#include <QByteArray>
|
||||
|
||||
#ifdef GPG_PROFILE
|
||||
#include <QTime>
|
||||
@ -35,109 +35,118 @@ namespace gpgQCAPlugin {
|
||||
|
||||
class GpgAction : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
public:
|
||||
struct Input
|
||||
{
|
||||
QString bin;
|
||||
GpgOp::Type op;
|
||||
bool opt_ascii, opt_noagent, opt_alwaystrust;
|
||||
QString opt_pubfile, opt_secfile;
|
||||
QStringList recip_ids;
|
||||
QString signer_id;
|
||||
QByteArray sig;
|
||||
QByteArray inkey;
|
||||
QString export_key_id;
|
||||
QString delete_key_fingerprint;
|
||||
struct Input
|
||||
{
|
||||
QString bin;
|
||||
GpgOp::Type op;
|
||||
bool opt_ascii, opt_noagent, opt_alwaystrust;
|
||||
QString opt_pubfile, opt_secfile;
|
||||
QStringList recip_ids;
|
||||
QString signer_id;
|
||||
QByteArray sig;
|
||||
QByteArray inkey;
|
||||
QString export_key_id;
|
||||
QString delete_key_fingerprint;
|
||||
|
||||
Input() : opt_ascii(false), opt_noagent(false), opt_alwaystrust(false) {}
|
||||
};
|
||||
Input()
|
||||
: opt_ascii(false)
|
||||
, opt_noagent(false)
|
||||
, opt_alwaystrust(false)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
struct Output
|
||||
{
|
||||
bool success;
|
||||
GpgOp::Error errorCode;
|
||||
GpgOp::KeyList keys;
|
||||
QString keyringFile;
|
||||
QString encryptedToId;
|
||||
bool wasSigned;
|
||||
QString signerId;
|
||||
QDateTime timestamp;
|
||||
GpgOp::VerifyResult verifyResult;
|
||||
QString homeDir;
|
||||
struct Output
|
||||
{
|
||||
bool success;
|
||||
GpgOp::Error errorCode;
|
||||
GpgOp::KeyList keys;
|
||||
QString keyringFile;
|
||||
QString encryptedToId;
|
||||
bool wasSigned;
|
||||
QString signerId;
|
||||
QDateTime timestamp;
|
||||
GpgOp::VerifyResult verifyResult;
|
||||
QString homeDir;
|
||||
|
||||
Output() : success(false), errorCode(GpgOp::ErrorUnknown), wasSigned(false) {}
|
||||
};
|
||||
Output()
|
||||
: success(false)
|
||||
, errorCode(GpgOp::ErrorUnknown)
|
||||
, wasSigned(false)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
Input input;
|
||||
Output output;
|
||||
Input input;
|
||||
Output output;
|
||||
|
||||
GpgAction(QObject *parent = 0);
|
||||
~GpgAction();
|
||||
void reset();
|
||||
void start();
|
||||
GpgAction(QObject *parent = nullptr);
|
||||
~GpgAction() override;
|
||||
void reset();
|
||||
void start();
|
||||
#ifdef QPIPE_SECURE
|
||||
void submitPassphrase(const QCA::SecureArray &a);
|
||||
void submitPassphrase(const QCA::SecureArray &a);
|
||||
#else
|
||||
void submitPassphrase(const QByteArray &a);
|
||||
void submitPassphrase(const QByteArray &a);
|
||||
#endif
|
||||
|
||||
public slots:
|
||||
QByteArray read();
|
||||
void write(const QByteArray &in);
|
||||
void endWrite();
|
||||
void cardOkay();
|
||||
QString readDiagnosticText();
|
||||
public Q_SLOTS:
|
||||
QByteArray read();
|
||||
void write(const QByteArray &in);
|
||||
void endWrite();
|
||||
void cardOkay();
|
||||
QString readDiagnosticText();
|
||||
|
||||
signals:
|
||||
void readyRead();
|
||||
void bytesWritten(int bytes);
|
||||
void finished();
|
||||
void needPassphrase(const QString &keyId);
|
||||
void needCard();
|
||||
void readyReadDiagnosticText();
|
||||
Q_SIGNALS:
|
||||
void readyRead();
|
||||
void bytesWritten(int bytes);
|
||||
void finished();
|
||||
void needPassphrase(const QString &keyId);
|
||||
void needCard();
|
||||
void readyReadDiagnosticText();
|
||||
|
||||
private:
|
||||
void submitCommand(const QByteArray &a);
|
||||
void submitCommand(const QByteArray &a);
|
||||
|
||||
// since str is taken as a value, it is ok to use the same variable for 'rest'
|
||||
QString nextArg(QString str, QString *rest = 0);
|
||||
void processStatusLine(const QString &line);
|
||||
void processResult(int code);
|
||||
void ensureDTextEmit();
|
||||
// since str is taken as a value, it is ok to use the same variable for 'rest'
|
||||
QString nextArg(QString str, QString *rest = nullptr);
|
||||
void processStatusLine(const QString &line);
|
||||
void processResult(int code);
|
||||
void ensureDTextEmit();
|
||||
|
||||
GPGProc proc;
|
||||
bool collectOutput, allowInput;
|
||||
LineConverter readConv, writeConv;
|
||||
bool readText, writeText;
|
||||
QByteArray buf_stdout, buf_stderr;
|
||||
bool useAux;
|
||||
QString passphraseKeyId;
|
||||
bool signing, decryptGood, signGood;
|
||||
GpgOp::Error curError;
|
||||
bool badPassphrase;
|
||||
bool need_submitPassphrase, need_cardOkay;
|
||||
QString diagnosticText;
|
||||
QCA::SafeTimer dtextTimer;
|
||||
bool utf8Output;
|
||||
GPGProc proc;
|
||||
bool collectOutput, allowInput;
|
||||
LineConverter readConv, writeConv;
|
||||
bool readText, writeText;
|
||||
QByteArray buf_stdout, buf_stderr;
|
||||
bool useAux;
|
||||
QString passphraseKeyId;
|
||||
bool signing, decryptGood, signGood;
|
||||
GpgOp::Error curError;
|
||||
bool badPassphrase;
|
||||
bool need_submitPassphrase, need_cardOkay;
|
||||
QString diagnosticText;
|
||||
QCA::SafeTimer dtextTimer;
|
||||
bool utf8Output;
|
||||
|
||||
#ifdef GPG_PROFILE
|
||||
QTime timer;
|
||||
QTime timer;
|
||||
#endif
|
||||
|
||||
private slots:
|
||||
void t_dtext();
|
||||
void proc_error(gpgQCAPlugin::GPGProc::Error e);
|
||||
void proc_finished(int exitCode);
|
||||
void proc_readyReadStdout();
|
||||
void proc_readyReadStderr();
|
||||
void proc_readyReadStatusLines();
|
||||
void proc_bytesWrittenStdin(int bytes);
|
||||
void proc_bytesWrittenAux(int bytes);
|
||||
void proc_bytesWrittenCommand(int);
|
||||
void proc_debug(const QString &str);
|
||||
void appendDiagnosticText(const QString &line);
|
||||
private Q_SLOTS:
|
||||
void t_dtext();
|
||||
void proc_error(gpgQCAPlugin::GPGProc::Error e);
|
||||
void proc_finished(int exitCode);
|
||||
void proc_readyReadStdout();
|
||||
void proc_readyReadStderr();
|
||||
void proc_readyReadStatusLines();
|
||||
void proc_bytesWrittenStdin(int bytes);
|
||||
void proc_bytesWrittenAux(int bytes);
|
||||
void proc_bytesWrittenCommand(int);
|
||||
void proc_debug(const QString &str);
|
||||
void appendDiagnosticText(const QString &line);
|
||||
};
|
||||
|
||||
|
||||
} // end namespace gpgQCAPlugin
|
||||
|
@ -17,9 +17,9 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "gpgop_p.h"
|
||||
#include "gpgop.h"
|
||||
#include "gpgaction.h"
|
||||
#include "gpgop_p.h"
|
||||
|
||||
namespace gpgQCAPlugin {
|
||||
|
||||
@ -27,351 +27,347 @@ namespace gpgQCAPlugin {
|
||||
// GpgOp
|
||||
//----------------------------------------------------------------------------
|
||||
GpgOp::Private::Private(GpgOp *_q)
|
||||
: QObject(_q)
|
||||
, sync(_q)
|
||||
, q(_q)
|
||||
, act(0)
|
||||
, waiting(false)
|
||||
: QObject(_q)
|
||||
, sync(_q)
|
||||
, q(_q)
|
||||
, act(nullptr)
|
||||
, waiting(false)
|
||||
{
|
||||
reset(ResetAll);
|
||||
reset(ResetAll);
|
||||
}
|
||||
|
||||
GpgOp::Private::~Private()
|
||||
{
|
||||
reset(ResetAll);
|
||||
reset(ResetAll);
|
||||
}
|
||||
|
||||
void GpgOp::Private::reset(ResetMode mode)
|
||||
{
|
||||
if(act)
|
||||
{
|
||||
act->disconnect(this);
|
||||
act->setParent(0);
|
||||
act->deleteLater();
|
||||
if (act) {
|
||||
act->disconnect(this);
|
||||
act->setParent(nullptr);
|
||||
act->deleteLater();
|
||||
|
||||
act = 0;
|
||||
}
|
||||
act = nullptr;
|
||||
}
|
||||
|
||||
if(mode >= ResetSessionAndData)
|
||||
{
|
||||
output = GpgAction::Output();
|
||||
result.clear();
|
||||
diagnosticText = QString();
|
||||
eventList.clear();
|
||||
}
|
||||
if (mode >= ResetSessionAndData) {
|
||||
output = GpgAction::Output();
|
||||
result.clear();
|
||||
diagnosticText = QString();
|
||||
eventList.clear();
|
||||
}
|
||||
|
||||
if(mode >= ResetAll)
|
||||
{
|
||||
opt_ascii = false;
|
||||
opt_noagent = false;
|
||||
opt_alwaystrust = false;
|
||||
opt_pubfile = QString();
|
||||
opt_secfile = QString();
|
||||
}
|
||||
if (mode >= ResetAll) {
|
||||
opt_ascii = false;
|
||||
opt_noagent = false;
|
||||
opt_alwaystrust = false;
|
||||
opt_pubfile = QString();
|
||||
opt_secfile = QString();
|
||||
}
|
||||
}
|
||||
|
||||
void GpgOp::Private::make_act(GpgOp::Type _op)
|
||||
{
|
||||
reset(ResetSessionAndData);
|
||||
reset(ResetSessionAndData);
|
||||
|
||||
op = _op;
|
||||
op = _op;
|
||||
|
||||
act = new GpgAction(this);
|
||||
act = new GpgAction(this);
|
||||
|
||||
connect(act, SIGNAL(readyRead()), SLOT(act_readyRead()));
|
||||
connect(act, SIGNAL(bytesWritten(int)), SLOT(act_bytesWritten(int)));
|
||||
connect(act, SIGNAL(needPassphrase(const QString &)), SLOT(act_needPassphrase(const QString &)));
|
||||
connect(act, SIGNAL(needCard()), SLOT(act_needCard()));
|
||||
connect(act, SIGNAL(finished()), SLOT(act_finished()));
|
||||
connect(act, SIGNAL(readyReadDiagnosticText()), SLOT(act_readyReadDiagnosticText()));
|
||||
connect(act, &GpgAction::readyRead, this, &GpgOp::Private::act_readyRead);
|
||||
connect(act, &GpgAction::bytesWritten, this, &GpgOp::Private::act_bytesWritten);
|
||||
connect(act, &GpgAction::needPassphrase, this, &GpgOp::Private::act_needPassphrase);
|
||||
connect(act, &GpgAction::needCard, this, &GpgOp::Private::act_needCard);
|
||||
connect(act, &GpgAction::finished, this, &GpgOp::Private::act_finished);
|
||||
connect(act, &GpgAction::readyReadDiagnosticText, this, &GpgOp::Private::act_readyReadDiagnosticText);
|
||||
|
||||
act->input.bin = bin;
|
||||
act->input.op = op;
|
||||
act->input.opt_ascii = opt_ascii;
|
||||
act->input.opt_noagent = opt_noagent;
|
||||
act->input.opt_alwaystrust = opt_alwaystrust;
|
||||
act->input.opt_pubfile = opt_pubfile;
|
||||
act->input.opt_secfile = opt_secfile;
|
||||
act->input.bin = bin;
|
||||
act->input.op = op;
|
||||
act->input.opt_ascii = opt_ascii;
|
||||
act->input.opt_noagent = opt_noagent;
|
||||
act->input.opt_alwaystrust = opt_alwaystrust;
|
||||
act->input.opt_pubfile = opt_pubfile;
|
||||
act->input.opt_secfile = opt_secfile;
|
||||
}
|
||||
|
||||
void GpgOp::Private::eventReady(const GpgOp::Event &e)
|
||||
{
|
||||
eventList += e;
|
||||
sync.conditionMet();
|
||||
eventList += e;
|
||||
sync.conditionMet();
|
||||
}
|
||||
|
||||
void GpgOp::Private::eventReady(GpgOp::Event::Type type)
|
||||
{
|
||||
GpgOp::Event e;
|
||||
e.type = type;
|
||||
eventReady(e);
|
||||
GpgOp::Event e;
|
||||
e.type = type;
|
||||
eventReady(e);
|
||||
}
|
||||
|
||||
void GpgOp::Private::eventReady(GpgOp::Event::Type type, int written)
|
||||
{
|
||||
GpgOp::Event e;
|
||||
e.type = type;
|
||||
e.written = written;
|
||||
eventReady(e);
|
||||
GpgOp::Event e;
|
||||
e.type = type;
|
||||
e.written = written;
|
||||
eventReady(e);
|
||||
}
|
||||
|
||||
void GpgOp::Private::eventReady(GpgOp::Event::Type type, const QString &keyId)
|
||||
{
|
||||
GpgOp::Event e;
|
||||
e.type = type;
|
||||
e.keyId = keyId;
|
||||
eventReady(e);
|
||||
GpgOp::Event e;
|
||||
e.type = type;
|
||||
e.keyId = keyId;
|
||||
eventReady(e);
|
||||
}
|
||||
|
||||
void GpgOp::Private::act_readyRead()
|
||||
{
|
||||
if(waiting)
|
||||
eventReady(GpgOp::Event::ReadyRead);
|
||||
else
|
||||
emit q->readyRead();
|
||||
if (waiting)
|
||||
eventReady(GpgOp::Event::ReadyRead);
|
||||
else
|
||||
emit q->readyRead();
|
||||
}
|
||||
|
||||
void GpgOp::Private::act_bytesWritten(int bytes)
|
||||
{
|
||||
if(waiting)
|
||||
eventReady(GpgOp::Event::BytesWritten, bytes);
|
||||
else
|
||||
emit q->bytesWritten(bytes);
|
||||
if (waiting)
|
||||
eventReady(GpgOp::Event::BytesWritten, bytes);
|
||||
else
|
||||
emit q->bytesWritten(bytes);
|
||||
}
|
||||
|
||||
void GpgOp::Private::act_needPassphrase(const QString &keyId)
|
||||
{
|
||||
if(waiting)
|
||||
eventReady(GpgOp::Event::NeedPassphrase, keyId);
|
||||
else
|
||||
emit q->needPassphrase(keyId);
|
||||
if (waiting)
|
||||
eventReady(GpgOp::Event::NeedPassphrase, keyId);
|
||||
else
|
||||
emit q->needPassphrase(keyId);
|
||||
}
|
||||
|
||||
void GpgOp::Private::act_needCard()
|
||||
{
|
||||
if(waiting)
|
||||
eventReady(GpgOp::Event::NeedCard);
|
||||
else
|
||||
emit q->needCard();
|
||||
if (waiting)
|
||||
eventReady(GpgOp::Event::NeedCard);
|
||||
else
|
||||
emit q->needCard();
|
||||
}
|
||||
|
||||
void GpgOp::Private::act_readyReadDiagnosticText()
|
||||
{
|
||||
QString s = act->readDiagnosticText();
|
||||
//printf("dtext ready: [%s]\n", qPrintable(s));
|
||||
diagnosticText += s;
|
||||
const QString s = act->readDiagnosticText();
|
||||
// printf("dtext ready: [%s]\n", qPrintable(s));
|
||||
diagnosticText += s;
|
||||
|
||||
if(waiting)
|
||||
eventReady(GpgOp::Event::ReadyReadDiagnosticText);
|
||||
else
|
||||
emit q->readyReadDiagnosticText();
|
||||
if (waiting)
|
||||
eventReady(GpgOp::Event::ReadyReadDiagnosticText);
|
||||
else
|
||||
emit q->readyReadDiagnosticText();
|
||||
}
|
||||
|
||||
void GpgOp::Private::act_finished()
|
||||
{
|
||||
#ifdef GPG_PROFILE
|
||||
if(op == GpgOp::Encrypt)
|
||||
printf("<< doEncrypt: %d >>\n", timer.elapsed());
|
||||
if (op == GpgOp::Encrypt)
|
||||
printf("<< doEncrypt: %d >>\n", timer.elapsed());
|
||||
#endif
|
||||
|
||||
result = act->read();
|
||||
diagnosticText += act->readDiagnosticText();
|
||||
output = act->output;
|
||||
result = act->read();
|
||||
diagnosticText += act->readDiagnosticText();
|
||||
output = act->output;
|
||||
|
||||
QMap<int, QString> errmap;
|
||||
errmap[GpgOp::ErrorProcess] = "ErrorProcess";
|
||||
errmap[GpgOp::ErrorPassphrase] = "ErrorPassphrase";
|
||||
errmap[GpgOp::ErrorFormat] = "ErrorFormat";
|
||||
errmap[GpgOp::ErrorSignerExpired] = "ErrorSignerExpired";
|
||||
errmap[GpgOp::ErrorEncryptExpired] = "ErrorEncryptExpired";
|
||||
errmap[GpgOp::ErrorEncryptUntrusted] = "ErrorEncryptUntrusted";
|
||||
errmap[GpgOp::ErrorEncryptInvalid] = "ErrorEncryptInvalid";
|
||||
errmap[GpgOp::ErrorDecryptNoKey] = "ErrorDecryptNoKey";
|
||||
errmap[GpgOp::ErrorUnknown] = "ErrorUnknown";
|
||||
if(output.success)
|
||||
diagnosticText += "GpgAction success\n";
|
||||
else
|
||||
diagnosticText += QString("GpgAction error: %1\n").arg(errmap[output.errorCode]);
|
||||
QMap<int, QString> errmap;
|
||||
errmap[GpgOp::ErrorProcess] = QStringLiteral("ErrorProcess");
|
||||
errmap[GpgOp::ErrorPassphrase] = QStringLiteral("ErrorPassphrase");
|
||||
errmap[GpgOp::ErrorFormat] = QStringLiteral("ErrorFormat");
|
||||
errmap[GpgOp::ErrorSignerExpired] = QStringLiteral("ErrorSignerExpired");
|
||||
errmap[GpgOp::ErrorEncryptExpired] = QStringLiteral("ErrorEncryptExpired");
|
||||
errmap[GpgOp::ErrorEncryptUntrusted] = QStringLiteral("ErrorEncryptUntrusted");
|
||||
errmap[GpgOp::ErrorEncryptInvalid] = QStringLiteral("ErrorEncryptInvalid");
|
||||
errmap[GpgOp::ErrorDecryptNoKey] = QStringLiteral("ErrorDecryptNoKey");
|
||||
errmap[GpgOp::ErrorUnknown] = QStringLiteral("ErrorUnknown");
|
||||
if (output.success)
|
||||
diagnosticText += QStringLiteral("GpgAction success\n");
|
||||
else
|
||||
diagnosticText += QStringLiteral("GpgAction error: %1\n").arg(errmap[output.errorCode]);
|
||||
|
||||
if(output.wasSigned)
|
||||
{
|
||||
QString s;
|
||||
if(output.verifyResult == GpgOp::VerifyGood)
|
||||
s = "VerifyGood";
|
||||
else if(output.verifyResult == GpgOp::VerifyBad)
|
||||
s = "VerifyBad";
|
||||
else
|
||||
s = "VerifyNoKey";
|
||||
diagnosticText += QString("wasSigned: verifyResult: %1\n").arg(s);
|
||||
}
|
||||
if (output.wasSigned) {
|
||||
QString s;
|
||||
if (output.verifyResult == GpgOp::VerifyGood)
|
||||
s = QStringLiteral("VerifyGood");
|
||||
else if (output.verifyResult == GpgOp::VerifyBad)
|
||||
s = QStringLiteral("VerifyBad");
|
||||
else
|
||||
s = QStringLiteral("VerifyNoKey");
|
||||
diagnosticText += QStringLiteral("wasSigned: verifyResult: %1\n").arg(s);
|
||||
}
|
||||
|
||||
//printf("diagnosticText:\n%s", qPrintable(diagnosticText));
|
||||
// printf("diagnosticText:\n%s", qPrintable(diagnosticText));
|
||||
|
||||
reset(ResetSession);
|
||||
reset(ResetSession);
|
||||
|
||||
if(waiting)
|
||||
eventReady(GpgOp::Event::Finished);
|
||||
else
|
||||
emit q->finished();
|
||||
if (waiting)
|
||||
eventReady(GpgOp::Event::Finished);
|
||||
else
|
||||
emit q->finished();
|
||||
}
|
||||
|
||||
GpgOp::GpgOp(const QString &bin, QObject *parent)
|
||||
:QObject(parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
d = new Private(this);
|
||||
d->bin = bin;
|
||||
d = new Private(this);
|
||||
d->bin = bin;
|
||||
}
|
||||
|
||||
GpgOp::~GpgOp()
|
||||
{
|
||||
delete d;
|
||||
delete d;
|
||||
}
|
||||
|
||||
void GpgOp::reset()
|
||||
{
|
||||
d->reset(ResetAll);
|
||||
d->reset(ResetAll);
|
||||
}
|
||||
|
||||
bool GpgOp::isActive() const
|
||||
{
|
||||
return (d->act ? true : false);
|
||||
return (d->act ? true : false);
|
||||
}
|
||||
|
||||
GpgOp::Type GpgOp::op() const
|
||||
{
|
||||
return d->op;
|
||||
return d->op;
|
||||
}
|
||||
|
||||
void GpgOp::setAsciiFormat(bool b)
|
||||
{
|
||||
d->opt_ascii = b;
|
||||
d->opt_ascii = b;
|
||||
}
|
||||
|
||||
void GpgOp::setDisableAgent(bool b)
|
||||
{
|
||||
d->opt_noagent = b;
|
||||
d->opt_noagent = b;
|
||||
}
|
||||
|
||||
void GpgOp::setAlwaysTrust(bool b)
|
||||
{
|
||||
d->opt_alwaystrust = b;
|
||||
d->opt_alwaystrust = b;
|
||||
}
|
||||
|
||||
void GpgOp::setKeyrings(const QString &pubfile, const QString &secfile)
|
||||
{
|
||||
d->opt_pubfile = pubfile;
|
||||
d->opt_secfile = secfile;
|
||||
d->opt_pubfile = pubfile;
|
||||
d->opt_secfile = secfile;
|
||||
}
|
||||
|
||||
void GpgOp::doCheck()
|
||||
{
|
||||
d->make_act(Check);
|
||||
d->act->start();
|
||||
d->make_act(Check);
|
||||
d->act->start();
|
||||
}
|
||||
|
||||
void GpgOp::doSecretKeyringFile()
|
||||
{
|
||||
d->make_act(SecretKeyringFile);
|
||||
d->act->start();
|
||||
d->make_act(SecretKeyringFile);
|
||||
d->act->start();
|
||||
}
|
||||
|
||||
void GpgOp::doPublicKeyringFile()
|
||||
{
|
||||
d->make_act(PublicKeyringFile);
|
||||
d->act->start();
|
||||
d->make_act(PublicKeyringFile);
|
||||
d->act->start();
|
||||
}
|
||||
|
||||
void GpgOp::doSecretKeys()
|
||||
{
|
||||
d->make_act(SecretKeys);
|
||||
d->act->start();
|
||||
d->make_act(SecretKeys);
|
||||
d->act->start();
|
||||
}
|
||||
|
||||
void GpgOp::doPublicKeys()
|
||||
{
|
||||
d->make_act(PublicKeys);
|
||||
d->act->start();
|
||||
d->make_act(PublicKeys);
|
||||
d->act->start();
|
||||
}
|
||||
|
||||
void GpgOp::doEncrypt(const QStringList &recip_ids)
|
||||
{
|
||||
#ifdef GPG_PROFILE
|
||||
d->timer.start();
|
||||
printf("<< doEncrypt >>\n");
|
||||
d->timer.start();
|
||||
printf("<< doEncrypt >>\n");
|
||||
#endif
|
||||
|
||||
d->make_act(Encrypt);
|
||||
d->act->input.recip_ids = recip_ids;
|
||||
d->act->start();
|
||||
d->make_act(Encrypt);
|
||||
d->act->input.recip_ids = recip_ids;
|
||||
d->act->start();
|
||||
}
|
||||
|
||||
void GpgOp::doDecrypt()
|
||||
{
|
||||
d->make_act(Decrypt);
|
||||
d->act->start();
|
||||
d->make_act(Decrypt);
|
||||
d->act->start();
|
||||
}
|
||||
|
||||
void GpgOp::doSign(const QString &signer_id)
|
||||
{
|
||||
d->make_act(Sign);
|
||||
d->act->input.signer_id = signer_id;
|
||||
d->act->start();
|
||||
d->make_act(Sign);
|
||||
d->act->input.signer_id = signer_id;
|
||||
d->act->start();
|
||||
}
|
||||
|
||||
void GpgOp::doSignAndEncrypt(const QString &signer_id, const QStringList &recip_ids)
|
||||
{
|
||||
d->make_act(SignAndEncrypt);
|
||||
d->act->input.signer_id = signer_id;
|
||||
d->act->input.recip_ids = recip_ids;
|
||||
d->act->start();
|
||||
d->make_act(SignAndEncrypt);
|
||||
d->act->input.signer_id = signer_id;
|
||||
d->act->input.recip_ids = recip_ids;
|
||||
d->act->start();
|
||||
}
|
||||
|
||||
void GpgOp::doSignClearsign(const QString &signer_id)
|
||||
{
|
||||
d->make_act(SignClearsign);
|
||||
d->act->input.signer_id = signer_id;
|
||||
d->act->start();
|
||||
d->make_act(SignClearsign);
|
||||
d->act->input.signer_id = signer_id;
|
||||
d->act->start();
|
||||
}
|
||||
|
||||
void GpgOp::doSignDetached(const QString &signer_id)
|
||||
{
|
||||
d->make_act(SignDetached);
|
||||
d->act->input.signer_id = signer_id;
|
||||
d->act->start();
|
||||
d->make_act(SignDetached);
|
||||
d->act->input.signer_id = signer_id;
|
||||
d->act->start();
|
||||
}
|
||||
|
||||
void GpgOp::doVerify()
|
||||
{
|
||||
d->make_act(Verify);
|
||||
d->act->start();
|
||||
d->make_act(Verify);
|
||||
d->act->start();
|
||||
}
|
||||
|
||||
void GpgOp::doVerifyDetached(const QByteArray &sig)
|
||||
{
|
||||
d->make_act(VerifyDetached);
|
||||
d->act->input.sig = sig;
|
||||
d->act->start();
|
||||
d->make_act(VerifyDetached);
|
||||
d->act->input.sig = sig;
|
||||
d->act->start();
|
||||
}
|
||||
|
||||
void GpgOp::doImport(const QByteArray &in)
|
||||
{
|
||||
d->make_act(Import);
|
||||
d->act->input.inkey = in;
|
||||
d->act->start();
|
||||
d->make_act(Import);
|
||||
d->act->input.inkey = in;
|
||||
d->act->start();
|
||||
}
|
||||
|
||||
void GpgOp::doExport(const QString &key_id)
|
||||
{
|
||||
d->make_act(Export);
|
||||
d->act->input.export_key_id = key_id;
|
||||
d->act->start();
|
||||
d->make_act(Export);
|
||||
d->act->input.export_key_id = key_id;
|
||||
d->act->start();
|
||||
}
|
||||
|
||||
void GpgOp::doDeleteKey(const QString &key_fingerprint)
|
||||
{
|
||||
d->make_act(DeleteKey);
|
||||
d->act->input.delete_key_fingerprint = key_fingerprint;
|
||||
d->act->start();
|
||||
d->make_act(DeleteKey);
|
||||
d->act->input.delete_key_fingerprint = key_fingerprint;
|
||||
d->act->start();
|
||||
}
|
||||
|
||||
#ifdef QPIPE_SECURE
|
||||
@ -380,110 +376,107 @@ void GpgOp::submitPassphrase(const QCA::SecureArray &a)
|
||||
void GpgOp::submitPassphrase(const QByteArray &a)
|
||||
#endif
|
||||
{
|
||||
d->act->submitPassphrase(a);
|
||||
d->act->submitPassphrase(a);
|
||||
}
|
||||
|
||||
void GpgOp::cardOkay()
|
||||
{
|
||||
d->act->cardOkay();
|
||||
d->act->cardOkay();
|
||||
}
|
||||
|
||||
QByteArray GpgOp::read()
|
||||
{
|
||||
if(d->act)
|
||||
{
|
||||
return d->act->read();
|
||||
}
|
||||
else
|
||||
{
|
||||
QByteArray a = d->result;
|
||||
d->result.clear();
|
||||
return a;
|
||||
}
|
||||
if (d->act) {
|
||||
return d->act->read();
|
||||
} else {
|
||||
const QByteArray a = d->result;
|
||||
d->result.clear();
|
||||
return a;
|
||||
}
|
||||
}
|
||||
|
||||
void GpgOp::write(const QByteArray &in)
|
||||
{
|
||||
d->act->write(in);
|
||||
d->act->write(in);
|
||||
}
|
||||
|
||||
void GpgOp::endWrite()
|
||||
{
|
||||
d->act->endWrite();
|
||||
d->act->endWrite();
|
||||
}
|
||||
|
||||
QString GpgOp::readDiagnosticText()
|
||||
{
|
||||
QString s = d->diagnosticText;
|
||||
d->diagnosticText = QString();
|
||||
return s;
|
||||
QString s = d->diagnosticText;
|
||||
d->diagnosticText = QString();
|
||||
return s;
|
||||
}
|
||||
|
||||
GpgOp::Event GpgOp::waitForEvent(int msecs)
|
||||
{
|
||||
if(!d->eventList.isEmpty())
|
||||
return d->eventList.takeFirst();
|
||||
if (!d->eventList.isEmpty())
|
||||
return d->eventList.takeFirst();
|
||||
|
||||
if(!d->act)
|
||||
return GpgOp::Event();
|
||||
if (!d->act)
|
||||
return GpgOp::Event();
|
||||
|
||||
d->waiting = true;
|
||||
d->sync.waitForCondition(msecs);
|
||||
d->waiting = false;
|
||||
if(!d->eventList.isEmpty())
|
||||
return d->eventList.takeFirst();
|
||||
else
|
||||
return GpgOp::Event();
|
||||
d->waiting = true;
|
||||
d->sync.waitForCondition(msecs);
|
||||
d->waiting = false;
|
||||
if (!d->eventList.isEmpty())
|
||||
return d->eventList.takeFirst();
|
||||
else
|
||||
return GpgOp::Event();
|
||||
}
|
||||
|
||||
bool GpgOp::success() const
|
||||
{
|
||||
return d->output.success;
|
||||
return d->output.success;
|
||||
}
|
||||
|
||||
GpgOp::Error GpgOp::errorCode() const
|
||||
{
|
||||
return d->output.errorCode;
|
||||
return d->output.errorCode;
|
||||
}
|
||||
|
||||
GpgOp::KeyList GpgOp::keys() const
|
||||
{
|
||||
return d->output.keys;
|
||||
return d->output.keys;
|
||||
}
|
||||
|
||||
QString GpgOp::keyringFile() const
|
||||
{
|
||||
return d->output.keyringFile;
|
||||
return d->output.keyringFile;
|
||||
}
|
||||
|
||||
QString GpgOp::homeDir() const
|
||||
{
|
||||
return d->output.homeDir;
|
||||
return d->output.homeDir;
|
||||
}
|
||||
|
||||
QString GpgOp::encryptedToId() const
|
||||
{
|
||||
return d->output.encryptedToId;
|
||||
return d->output.encryptedToId;
|
||||
}
|
||||
|
||||
bool GpgOp::wasSigned() const
|
||||
{
|
||||
return d->output.wasSigned;
|
||||
return d->output.wasSigned;
|
||||
}
|
||||
|
||||
QString GpgOp::signerId() const
|
||||
{
|
||||
return d->output.signerId;
|
||||
return d->output.signerId;
|
||||
}
|
||||
|
||||
QDateTime GpgOp::timestamp() const
|
||||
{
|
||||
return d->output.timestamp;
|
||||
return d->output.timestamp;
|
||||
}
|
||||
|
||||
GpgOp::VerifyResult GpgOp::verifyResult() const
|
||||
{
|
||||
return d->output.verifyResult;
|
||||
return d->output.verifyResult;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -20,191 +20,203 @@
|
||||
#ifndef GPGOP_H
|
||||
#define GPGOP_H
|
||||
|
||||
#include <QtCrypto>
|
||||
#include "qpipe.h"
|
||||
#include <QtCrypto>
|
||||
|
||||
namespace gpgQCAPlugin {
|
||||
|
||||
class GpgOp : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum Type
|
||||
{
|
||||
Check, // --version
|
||||
SecretKeyringFile, // --list-secret-keys
|
||||
PublicKeyringFile, // --list-public-keys
|
||||
SecretKeys, // --fixed-list-mode --with-colons --list-secret-keys
|
||||
PublicKeys, // --fixed-list-mode --with-colons --list-public-keys
|
||||
Encrypt, // --encrypt
|
||||
Decrypt, // --decrypt
|
||||
Sign, // --sign
|
||||
SignAndEncrypt, // --sign --encrypt
|
||||
SignClearsign, // --clearsign
|
||||
SignDetached, // --detach-sign
|
||||
Verify, // --verify
|
||||
VerifyDetached, // --verify
|
||||
Import, // --import
|
||||
Export, // --export
|
||||
DeleteKey // --delete-key
|
||||
};
|
||||
enum Type
|
||||
{
|
||||
Check, // --version
|
||||
SecretKeyringFile, // --list-secret-keys
|
||||
PublicKeyringFile, // --list-public-keys
|
||||
SecretKeys, // --fixed-list-mode --with-colons --list-secret-keys
|
||||
PublicKeys, // --fixed-list-mode --with-colons --list-public-keys
|
||||
Encrypt, // --encrypt
|
||||
Decrypt, // --decrypt
|
||||
Sign, // --sign
|
||||
SignAndEncrypt, // --sign --encrypt
|
||||
SignClearsign, // --clearsign
|
||||
SignDetached, // --detach-sign
|
||||
Verify, // --verify
|
||||
VerifyDetached, // --verify
|
||||
Import, // --import
|
||||
Export, // --export
|
||||
DeleteKey // --delete-key
|
||||
};
|
||||
|
||||
enum VerifyResult
|
||||
{
|
||||
VerifyGood, // good sig
|
||||
VerifyBad, // bad sig
|
||||
VerifyNoKey // we don't have signer's public key
|
||||
};
|
||||
enum VerifyResult
|
||||
{
|
||||
VerifyGood, // good sig
|
||||
VerifyBad, // bad sig
|
||||
VerifyNoKey // we don't have signer's public key
|
||||
};
|
||||
|
||||
enum Error
|
||||
{
|
||||
ErrorProcess, // startup, process, or ipc error
|
||||
ErrorPassphrase, // passphrase was either wrong or not provided
|
||||
ErrorFormat, // input format was bad
|
||||
ErrorSignerExpired, // signing key is expired
|
||||
ErrorEncryptExpired, // encrypting key is expired
|
||||
ErrorEncryptUntrusted, // encrypting key is untrusted
|
||||
ErrorEncryptInvalid, // encrypting key is invalid in some way
|
||||
ErrorDecryptNoKey, // missing decrypt key
|
||||
ErrorUnknown, // other error
|
||||
ErrorSignerRevoked, // signing key is revoked
|
||||
ErrorSignatureExpired, // signature is expired
|
||||
ErrorEncryptRevoked // encrypting key is revoked
|
||||
};
|
||||
enum Error
|
||||
{
|
||||
ErrorProcess, // startup, process, or ipc error
|
||||
ErrorPassphrase, // passphrase was either wrong or not provided
|
||||
ErrorFormat, // input format was bad
|
||||
ErrorSignerExpired, // signing key is expired
|
||||
ErrorEncryptExpired, // encrypting key is expired
|
||||
ErrorEncryptUntrusted, // encrypting key is untrusted
|
||||
ErrorEncryptInvalid, // encrypting key is invalid in some way
|
||||
ErrorDecryptNoKey, // missing decrypt key
|
||||
ErrorUnknown, // other error
|
||||
ErrorSignerRevoked, // signing key is revoked
|
||||
ErrorSignatureExpired, // signature is expired
|
||||
ErrorEncryptRevoked // encrypting key is revoked
|
||||
};
|
||||
|
||||
class Event
|
||||
{
|
||||
public:
|
||||
enum Type
|
||||
{
|
||||
None,
|
||||
ReadyRead,
|
||||
BytesWritten,
|
||||
Finished,
|
||||
NeedPassphrase,
|
||||
NeedCard,
|
||||
ReadyReadDiagnosticText
|
||||
};
|
||||
class Event
|
||||
{
|
||||
public:
|
||||
enum Type
|
||||
{
|
||||
None,
|
||||
ReadyRead,
|
||||
BytesWritten,
|
||||
Finished,
|
||||
NeedPassphrase,
|
||||
NeedCard,
|
||||
ReadyReadDiagnosticText
|
||||
};
|
||||
|
||||
Type type;
|
||||
int written; // BytesWritten
|
||||
QString keyId; // NeedPassphrase
|
||||
Type type;
|
||||
int written; // BytesWritten
|
||||
QString keyId; // NeedPassphrase
|
||||
|
||||
Event() : type(None), written(0) {}
|
||||
};
|
||||
Event()
|
||||
: type(None)
|
||||
, written(0)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class KeyItem
|
||||
{
|
||||
public:
|
||||
enum Type
|
||||
{
|
||||
RSA,
|
||||
DSA,
|
||||
ElGamal,
|
||||
Unknown
|
||||
};
|
||||
class KeyItem
|
||||
{
|
||||
public:
|
||||
enum Type
|
||||
{
|
||||
RSA,
|
||||
DSA,
|
||||
ElGamal,
|
||||
Unknown
|
||||
};
|
||||
|
||||
enum Caps
|
||||
{
|
||||
Encrypt = 0x01,
|
||||
Sign = 0x02,
|
||||
Certify = 0x04,
|
||||
Auth = 0x08
|
||||
};
|
||||
enum Caps
|
||||
{
|
||||
Encrypt = 0x01,
|
||||
Sign = 0x02,
|
||||
Certify = 0x04,
|
||||
Auth = 0x08
|
||||
};
|
||||
|
||||
QString id;
|
||||
Type type;
|
||||
int bits;
|
||||
QDateTime creationDate;
|
||||
QDateTime expirationDate;
|
||||
int caps; // flags OR'd together
|
||||
QString fingerprint;
|
||||
QString id;
|
||||
Type type;
|
||||
int bits;
|
||||
QDateTime creationDate;
|
||||
QDateTime expirationDate;
|
||||
int caps; // flags OR'd together
|
||||
QString fingerprint;
|
||||
|
||||
KeyItem() : type(Unknown), bits(0), caps(0) {}
|
||||
};
|
||||
KeyItem()
|
||||
: type(Unknown)
|
||||
, bits(0)
|
||||
, caps(0)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class Key
|
||||
{
|
||||
public:
|
||||
QList<KeyItem> keyItems; // first item is primary
|
||||
QStringList userIds;
|
||||
bool isTrusted;
|
||||
class Key
|
||||
{
|
||||
public:
|
||||
QList<KeyItem> keyItems; // first item is primary
|
||||
QStringList userIds;
|
||||
bool isTrusted;
|
||||
|
||||
Key() : isTrusted(false) {}
|
||||
};
|
||||
typedef QList<Key> KeyList;
|
||||
Key()
|
||||
: isTrusted(false)
|
||||
{
|
||||
}
|
||||
};
|
||||
typedef QList<Key> KeyList;
|
||||
|
||||
explicit GpgOp(const QString &bin, QObject *parent = 0);
|
||||
~GpgOp();
|
||||
explicit GpgOp(const QString &bin, QObject *parent = nullptr);
|
||||
~GpgOp() override;
|
||||
|
||||
void reset();
|
||||
void reset();
|
||||
|
||||
bool isActive() const;
|
||||
Type op() const;
|
||||
bool isActive() const;
|
||||
Type op() const;
|
||||
|
||||
void setAsciiFormat(bool b);
|
||||
void setDisableAgent(bool b);
|
||||
void setAlwaysTrust(bool b);
|
||||
void setKeyrings(const QString &pubfile, const QString &secfile); // for keylists and import
|
||||
void setAsciiFormat(bool b);
|
||||
void setDisableAgent(bool b);
|
||||
void setAlwaysTrust(bool b);
|
||||
void setKeyrings(const QString &pubfile, const QString &secfile); // for keylists and import
|
||||
|
||||
void doCheck();
|
||||
void doSecretKeyringFile();
|
||||
void doPublicKeyringFile();
|
||||
void doSecretKeys();
|
||||
void doPublicKeys();
|
||||
void doEncrypt(const QStringList &recip_ids);
|
||||
void doDecrypt();
|
||||
void doSign(const QString &signer_id);
|
||||
void doSignAndEncrypt(const QString &signer_id, const QStringList &recip_ids);
|
||||
void doSignClearsign(const QString &signer_id);
|
||||
void doSignDetached(const QString &signer_id);
|
||||
void doVerify();
|
||||
void doVerifyDetached(const QByteArray &sig);
|
||||
void doImport(const QByteArray &in);
|
||||
void doExport(const QString &key_id);
|
||||
void doDeleteKey(const QString &key_fingerprint);
|
||||
void doCheck();
|
||||
void doSecretKeyringFile();
|
||||
void doPublicKeyringFile();
|
||||
void doSecretKeys();
|
||||
void doPublicKeys();
|
||||
void doEncrypt(const QStringList &recip_ids);
|
||||
void doDecrypt();
|
||||
void doSign(const QString &signer_id);
|
||||
void doSignAndEncrypt(const QString &signer_id, const QStringList &recip_ids);
|
||||
void doSignClearsign(const QString &signer_id);
|
||||
void doSignDetached(const QString &signer_id);
|
||||
void doVerify();
|
||||
void doVerifyDetached(const QByteArray &sig);
|
||||
void doImport(const QByteArray &in);
|
||||
void doExport(const QString &key_id);
|
||||
void doDeleteKey(const QString &key_fingerprint);
|
||||
|
||||
#ifdef QPIPE_SECURE
|
||||
void submitPassphrase(const QCA::SecureArray &a);
|
||||
void submitPassphrase(const QCA::SecureArray &a);
|
||||
#else
|
||||
void submitPassphrase(const QByteArray &a);
|
||||
void submitPassphrase(const QByteArray &a);
|
||||
#endif
|
||||
void cardOkay();
|
||||
void cardOkay();
|
||||
|
||||
// for encrypt, decrypt, sign, verify, export
|
||||
QByteArray read();
|
||||
void write(const QByteArray &in);
|
||||
void endWrite();
|
||||
// for encrypt, decrypt, sign, verify, export
|
||||
QByteArray read();
|
||||
void write(const QByteArray &in);
|
||||
void endWrite();
|
||||
|
||||
QString readDiagnosticText();
|
||||
QString readDiagnosticText();
|
||||
|
||||
// for synchronous operation
|
||||
Event waitForEvent(int msecs = -1);
|
||||
// for synchronous operation
|
||||
Event waitForEvent(int msecs = -1);
|
||||
|
||||
// results
|
||||
bool success() const;
|
||||
Error errorCode() const;
|
||||
KeyList keys() const; // Keys
|
||||
QString keyringFile() const; // KeyringFile
|
||||
QString homeDir() const; // GnuPG home directory
|
||||
QString encryptedToId() const; // Decrypt (for ErrorDecryptNoKey)
|
||||
bool wasSigned() const; // Decrypt
|
||||
QString signerId() const; // Verify
|
||||
QDateTime timestamp() const; // Verify
|
||||
VerifyResult verifyResult() const; // Verify
|
||||
// results
|
||||
bool success() const;
|
||||
Error errorCode() const;
|
||||
KeyList keys() const; // Keys
|
||||
QString keyringFile() const; // KeyringFile
|
||||
QString homeDir() const; // GnuPG home directory
|
||||
QString encryptedToId() const; // Decrypt (for ErrorDecryptNoKey)
|
||||
bool wasSigned() const; // Decrypt
|
||||
QString signerId() const; // Verify
|
||||
QDateTime timestamp() const; // Verify
|
||||
VerifyResult verifyResult() const; // Verify
|
||||
|
||||
Q_SIGNALS:
|
||||
void readyRead();
|
||||
void bytesWritten(int bytes);
|
||||
void finished();
|
||||
void needPassphrase(const QString &keyId);
|
||||
void needCard();
|
||||
void readyReadDiagnosticText();
|
||||
void readyRead();
|
||||
void bytesWritten(int bytes);
|
||||
void finished();
|
||||
void needPassphrase(const QString &keyId);
|
||||
void needCard();
|
||||
void readyReadDiagnosticText();
|
||||
|
||||
private:
|
||||
class Private;
|
||||
friend class Private;
|
||||
Private *d;
|
||||
class Private;
|
||||
friend class Private;
|
||||
Private *d;
|
||||
};
|
||||
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user