diff --git a/CMakeLists.txt b/CMakeLists.txt index 93c7070d..690ec27f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -84,6 +84,7 @@ add_library(xcalib STATIC) add_executable(${CMAKE_PROJECT_NAME} img/imgres.qrc lib/main.cpp ${UI_FILES} ${PROJECT_BINARY_DIR}/local.h) add_executable(xcadoc ${PROJECT_BINARY_DIR}/local.h) +add_executable(xcaexport ${PROJECT_BINARY_DIR}/local.h) include_directories(${PROJECT_BINARY_DIR} ${PROJECT_SOURCE_DIR}) @@ -136,6 +137,7 @@ target_link_libraries(xcalib target_link_libraries(xcadoc OpenSSL::Crypto ${QT}::Core ${ASAN_LIB} ) +target_link_libraries(xcaexport ${QT}::Core ${ASAN_LIB}) target_link_libraries(${CMAKE_PROJECT_NAME} ${ASAN_LIB} xcalib) if (APPLE) @@ -251,6 +253,11 @@ elseif(WIN32) --dir ${CMAKE_BINARY_DIR} --no-translations COMMENT "Running windeployqt on xcadoc ..." ) + add_custom_command(TARGET xcaexport POST_BUILD + COMMAND ${WINDEPLOYQT_EXECUTABLE} $ + --dir ${CMAKE_BINARY_DIR} --no-translations + COMMENT "Running windeployqt on xcaexport ..." + ) set(QT_USE_QTMAIN TRUE) set(CPACK_GENERATOR WIX) set(CPACK_PACKAGE_VENDOR "Christian Hohnstädt") diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt index 51cccf11..525050e4 100644 --- a/doc/CMakeLists.txt +++ b/doc/CMakeLists.txt @@ -85,15 +85,28 @@ if(SPHINX) ) add_custom_command( OUTPUT ${RST}/arguments.rst + DEPENDS xcadoc COMMAND xcadoc rst ${RST}/arguments.rst COMMENT "Generate 'rst' commandline documentation" ) - add_dependencies(${CMAKE_PROJECT_NAME} sphinx-html) target_sources(${CMAKE_PROJECT_NAME} PRIVATE ${HTML_DEST}) + foreach(EXPORT_TOPIC x509 x509-clp key key-clp request revocation) + set(EXPORT_DEST ${RST}/export-${EXPORT_TOPIC}.rst) + add_custom_command( + OUTPUT ${EXPORT_DEST} + DEPENDS xcaexport + COMMAND xcaexport ${EXPORT_TOPIC} ${EXPORT_DEST} + COMMENT "Generate '${EXPORT_TOPIC}' export documentation" + ) + list(APPEND EXPORT_TOPICS ${EXPORT_DEST}) + endforeach() + + add_dependencies(${CMAKE_PROJECT_NAME} sphinx-html) add_custom_target(sphinx-src DEPENDS ${D}/rst.stamp ${RST}/database_schema.sql ${RST}/arguments.rst + ${EXPORT_TOPICS} ) if (UNIX) diff --git a/doc/rst/certificates.rst b/doc/rst/certificates.rst index c98581b3..e9fd1dc3 100644 --- a/doc/rst/certificates.rst +++ b/doc/rst/certificates.rst @@ -78,37 +78,15 @@ also displayed in a format defined in RFC2253 for copy&paste. Certificate Export ------------------ -- **Clipboard:** Copy all selected certificates to the clipboard as PEM file +- **Clipboard:** Export certificates to the clipboard +- **Clipboard format:** The format for the clipboard can be selected as follows: + +.. include:: export-x509-clp.rst + - **File:** Export to external file. The filename can be selected in the export dialog and the Export format: - - **PEM:** PEM encoded - - **PEM with Certificate chain:** PEM encoded certificate - and all issuers up to the root certificate in one file - - **DER:** DER encoded certificate. - - **PKCS#7:** DER encoded PKCS#7 structure containing the certificate. - - **PKCS#7 chain:** DER encoded PKCS#7 structure containing - the selected certificate and all issuers up to the root certificate. - - **PKCS#7 selected certificates:** DER encoded PKCS#7 structure - containing all selected certificates. - - **PKCS#12:** PKCS#12 structure containing the certificate - and the corresponding private key - - **PKCS#12 chain:** PKCS#12 structure containing the certificate, the - corresponding private key and the chain of all issuers certificates. - - **PEM cert + key:** concatenation of the private key and certificate - in a format used by apache or the X509 patch for OpenSSH. - - **PEM cert + PKCS8 key:** concatenation of the - private key in PKCS#8 format and certificate. - - **OpenVPN:** The selected certificate, its corresponding private key - and all issuing certificates in one text file with tags suitable - as part of an OpenVPN configuration file. - - **vCalendar (*.ics):** expiry notifications for all selected certificates - to be imported into your favorite calendar app. - - **CA vCalendar (*.ics):** expiry notifications for the CA certificate, - valid, issued cdrtificates and the latest CRL. - - **OpenSSL config:** Create an OpenSSL config file from the content of - this certificate, which can be used to generate a similar certificate - with openssl: `openssl req -new -x509 -config ` +.. include:: export-x509.rst - **Token:** Store certificate on the Security token containing the private key. - **Other token:** Store certificate on any Security token. diff --git a/doc/rst/privatekey.rst b/doc/rst/privatekey.rst index fba24206..52400123 100644 --- a/doc/rst/privatekey.rst +++ b/doc/rst/privatekey.rst @@ -86,21 +86,16 @@ Key Export Keys can be exported by either selecting the key and pressing *Export* or by using the context-menu. -It may be chosen to export the key to the clipboard as PEM public, SSH2 public -or unencrypted PEM private format. -In case of a file export a dialog-box opens where next to the filename -one of the following formats may be selected: -- **PEM public:** the public part of the key in PEM format -- **DER public:** the public part of the key in DER format -- **SSH2 public:** the public part of the key in SSH2 format -- **PEM private:** the private key unencrypt in PEM format -- **PKCS#8 encrypted:** the encrypted private key in PKCS#8 format -- **DER private:** the private key in binary DER format -- **PEM encrypted:** the private key in PEM format with an OpenSSL specific - extensions for encryption -- **PKCS#8 unencrypted:** the private key unencrypted in PKCS#8 format -- **SSH2 private:** the private key unencrypted in SSH2 format +- **Clipboard:** Export the private or public key to the clipboard +- **Clipboard format:** The format for the clipboard-export can be selected as follows: + +.. include:: export-key-clp.rst + +- **File:** Export to external file. + The filename can be selected in the export dialog and the Export format: + +.. include:: export-key.rst The filename is the internal name plus a *pem*, *der*, *pk8*, *pub* or *priv* suffix. When changing the file-format, the suffix of the filename changes @@ -112,4 +107,3 @@ Of course, encryption does not make sense if the private part is not exported. When exporting the key via SQL from the database, see :ref:`extracting-items` openssl asks for the password, which is either the database password or its own password in case the password type is *private*. - diff --git a/doc/rst/requests.rst b/doc/rst/requests.rst index eedd5c43..82303579 100644 --- a/doc/rst/requests.rst +++ b/doc/rst/requests.rst @@ -50,8 +50,10 @@ Request Export Requests can be exported by the context-menu or by the button on the right. - **Clipboard** Writes all selected requests in PEM format to the Clipboard. -- **File** Write the request into a file in PEM or DER format, or as - OpenSSL configuration file format. +- **File:** Write the request into a file. + The filename can be selected in the export dialog and the Export format: + +.. include:: export-request.rst The OpenSSL config file format can be used to generate a similar request with openssl `openssl req -new -config ` diff --git a/doc/rst/revocationlist.rst b/doc/rst/revocationlist.rst index b5a680d6..c6b4caef 100644 --- a/doc/rst/revocationlist.rst +++ b/doc/rst/revocationlist.rst @@ -34,6 +34,19 @@ There is also a commandline option to issue a CRL: xca --crlgen="My Ca" --pem --print +.. index:: crlexport (crlexport) + +CRL Export +---------- + +Cetificate Revocation Lists can be exported by the context-menu or by the button on the right. + +- **Clipboard** Writes all selected requests in PEM format to the Clipboard. +- **File:** Write the request into a file. + The filename can be selected in the export dialog and the Export format: + +.. include:: export-revocation.rst + .. index:: crlmanage (crlmanage) Manage revocations diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 426e8b9b..727c198a 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -1,5 +1,6 @@ list(APPEND xcadoc_sources arguments.cpp arguments.h xcadoc.cpp) +list(APPEND xcaexport_sources pki_export.cpp pki_export.h xcaexport.cpp) list(APPEND xcalib_sources BioByteArray.cpp dbhistory.cpp pki_key.cpp @@ -49,6 +50,7 @@ endmacro() ExpandSources(xcalib) ExpandSources(xcadoc) +ExpandSources(xcaexport) macro(Test name) set(${name}_sources ${ARGN}) diff --git a/lib/pki_export.cpp b/lib/pki_export.cpp index c116209d..21af6c7c 100644 --- a/lib/pki_export.cpp +++ b/lib/pki_export.cpp @@ -62,7 +62,7 @@ void pki_export::init_elements() elements = QList { new pki_export( 1, x509, "crt", "PEM", F_PEM | F_USUAL | F_SINGLE | F_CLIPBOARD, tr("PEM Text format with headers")), -new pki_export( 3, x509, "pem", "PEM", F_PEM | F_MULTI, tr("Concatenated list of all selected items in one PEM text file")), +new pki_export( 3, x509, "pem", tr("PEM selected"), F_PEM | F_MULTI, tr("Concatenated list of all selected items in one PEM text file")), new pki_export( 2, x509, "pem", tr("PEM chain"), F_PEM | F_USUAL | F_CHAIN | F_SINGLE | F_CLIPBOARD, tr("Concatenated text format of the complete certificate chain in one PEM file")), new pki_export( 4, x509, "ovpn","OpenVPN", F_PEM | F_OVPN | F_CHAIN | F_PRIVATE | F_SINGLE, tr("The complete certificate chain and the private key of the selected certificate with tags usable in OpenVPN configuration files")), new pki_export( 6, x509, "pem", tr("PEM + key"), F_PEM | F_PRIVATE| F_SINGLE | F_CLIPBOARD, tr("Concatenation of the certificate and the unencrypted private key in one PEM file")), diff --git a/lib/xcaexport.cpp b/lib/xcaexport.cpp new file mode 100644 index 00000000..9624bb66 --- /dev/null +++ b/lib/xcaexport.cpp @@ -0,0 +1,59 @@ +#include +#include +#include +#include + +#include "pki_export.h" + +static const QMap typeMap = { + {"x509", x509}, + {"x509-clp", x509}, + {"key", asym_key}, + {"key-clp", asym_key}, + {"request", x509_req}, + {"revocation", revocation}, + {"template", tmpl}, +}; + +static void noop(QtMsgType , const QMessageLogContext &, const QString &) +{ +} + +static QString make_doc(const QString &which) +{ + pki_type typ = typeMap[which]; + int match = which.endsWith("-clp") ? F_CLIPBOARD : 0; + QString doc; + for (const pki_export *exp : pki_export::select(typ, 0)) { + if (exp->match_all(match)) { + doc += QString(" - **%1:** (\\*.%2) %3\n").arg(exp->desc).arg(exp->extension).arg(exp->help); + } + } + return doc; +} + +int main(int argc, char *argv[]) +{ + qInstallMessageHandler(noop); + + if (argc < 2) { + qWarning() << "Need type argument: "; + return EXIT_FAILURE; + } + pki_export::init_elements(); + if (!typeMap.contains(argv[1])) { + qWarning() << QString("Unknown type: %1").arg(argv[1]); + return EXIT_FAILURE; + } + QByteArray doc = make_doc(argv[1]).toUtf8(); + if (argc > 2) { + QFile f(argv[2]); + f.open(QIODevice::WriteOnly); + f.write(doc); + f.close(); + } else { + QTextStream out(stdout); + out << doc; + } + return EXIT_SUCCESS; +} diff --git a/widgets/CrlTreeView.cpp b/widgets/CrlTreeView.cpp index 5782fb02..57d5173a 100644 --- a/widgets/CrlTreeView.cpp +++ b/widgets/CrlTreeView.cpp @@ -69,5 +69,6 @@ ExportDialog *CrlTreeView::exportDialog(const QModelIndexList &indexes) tr("Revocation list export"), tr("CRL ( *.pem *.der *.crl )") + ";;" + tr("vCalendar entry ( *.ics )"), indexes, QPixmap(":revImg"), - pki_export::select(revocation, basemodel->exportFlags(indexes))); + pki_export::select(revocation, basemodel->exportFlags(indexes)), + "crlexport"); } diff --git a/widgets/TempTreeView.cpp b/widgets/TempTreeView.cpp index 0b61cafb..926aa933 100644 --- a/widgets/TempTreeView.cpp +++ b/widgets/TempTreeView.cpp @@ -124,6 +124,5 @@ ExportDialog *TempTreeView::exportDialog(const QModelIndexList &indexes) tr("Template export"), tr("XCA Templates ( *.xca )"), indexes, QPixmap(":tempImg"), - pki_export::select(tmpl, basemodel->exportFlags(indexes)), - "templateexport"); + pki_export::select(tmpl, basemodel->exportFlags(indexes))); }