File indexing completed on 2024-05-19 15:50:18

0001 /*
0002  Copyright (C) 2003 Justin Karneges <justin@affinix.com>
0003  Copyright (C) 2005 Brad Hards <bradh@frogmouth.net>
0004 
0005  Permission is hereby granted, free of charge, to any person obtaining a copy
0006  of this software and associated documentation files (the "Software"), to deal
0007  in the Software without restriction, including without limitation the rights
0008  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
0009  copies of the Software, and to permit persons to whom the Software is
0010  furnished to do so, subject to the following conditions:
0011 
0012  The above copyright notice and this permission notice shall be included in
0013  all copies or substantial portions of the Software.
0014 
0015  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0016  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0017  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
0018  AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
0019  AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
0020  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
0021 */
0022 
0023 #include <QtCrypto>
0024 
0025 #include <QCoreApplication>
0026 #include <QFile>
0027 
0028 #include <iostream>
0029 
0030 #ifdef QT_STATICPLUGIN
0031 #include "import_plugins.h"
0032 #endif
0033 
0034 // dump out information about some part of the certificate
0035 // we use this same approach for information about the subject
0036 // of the certificate, and also about the issuer of the certificate
0037 static void dumpCertificateInfo(const QCA::CertificateInfo &info)
0038 {
0039     std::cout << "  Organization: " << std::endl;
0040 
0041     // Note that a single certificate can apply to more than one
0042     // organisation. QCA::Certificate is a multimap, so when you
0043     // ask for the values associated with a parameter, it returns
0044     // a list.
0045     QList<QString> orgInfoList = info.values(QCA::Organization);
0046 
0047     // foreach() interates over each value in the list, and we dump
0048     // out each value. Note that is uncommon for a certificate to
0049     // actually contain multiple values for a single parameter.
0050     QString organization;
0051     foreach (organization, orgInfoList) {
0052         std::cout << "    " << qPrintable(organization) << std::endl;
0053     }
0054 
0055     std::cout << "  Country: " << std::endl;
0056     // As above, however this shows a more compact way to represent
0057     // the iteration and output.
0058     foreach (QString country, info.values(QCA::Country)) { // clazy:exclude=container-anti-pattern
0059         std::cout << "    " << qPrintable(country) << std::endl;
0060     }
0061 }
0062 
0063 // This is just a convenience routine
0064 static void dumpSubjectInfo(const QCA::CertificateInfo &subject)
0065 {
0066     std::cout << "Subject: " << std::endl;
0067 
0068     dumpCertificateInfo(subject);
0069 }
0070 
0071 // This is just a convenience routine
0072 static void dumpIssuerInfo(const QCA::CertificateInfo &issuer)
0073 {
0074     std::cout << "Issuer: " << std::endl;
0075 
0076     dumpCertificateInfo(issuer);
0077 }
0078 
0079 int main(int argc, char **argv)
0080 {
0081     // the Initializer object sets things up, and
0082     // also does cleanup when it goes out of scope
0083     QCA::Initializer init;
0084 
0085     QCoreApplication app(argc, argv);
0086 
0087     // We need to ensure that we have certificate handling support
0088     if (!QCA::isSupported("cert")) {
0089         std::cout << "Sorry, no PKI certificate support" << std::endl;
0090         return 1;
0091     }
0092 
0093     // We are going to work with a number of certificates, and a
0094     // QList is a great template class for that
0095     QList<QCA::Certificate> certlist;
0096 
0097     // We do two different cases - if we provide an argument, it is taken
0098     // as a filename to read the keys from. If there is no argument, we just
0099     // read from the system store certificates.
0100     if (argc >= 2) {
0101         // we are going to read the certificates in using a single call
0102         // which requires a CertificateCollection.
0103         QCA::CertificateCollection filecerts;
0104         // The conversion can be tested (although you don't have to) to find out if it
0105         // worked.
0106         QCA::ConvertResult importResult;
0107         // This imports all the PEM encoded certificates from the file specified as the argument
0108         // Note that you pass in a pointer to the result argument.
0109         filecerts = QCA::CertificateCollection::fromFlatTextFile(QFile::decodeName(argv[1]), &importResult);
0110         if (QCA::ConvertGood == importResult) {
0111             std::cout << "Import succeeded" << std::endl;
0112             // this turns the CertificateCollection into a QList of Certificate objects
0113             certlist = filecerts.certificates();
0114         }
0115     } else {
0116         // we have no arguments, so just use the system certificates
0117         if (!QCA::haveSystemStore()) {
0118             std::cout << "System certificates not available" << std::endl;
0119             return 2;
0120         }
0121 
0122         // Similar to above, except we just want the system certificates
0123         QCA::CertificateCollection systemcerts = QCA::systemStore();
0124 
0125         // this turns the CertificateCollection into a QList of Certificate objects
0126         certlist = systemcerts.certificates();
0127     }
0128 
0129     std::cout << "Number of certificates: " << certlist.count() << std::endl;
0130 
0131     QCA::Certificate cert;
0132     foreach (cert, certlist) {
0133         std::cout << "Serial Number:";
0134         // the serial number of the certificate is a QCA::BigInteger, but we can
0135         // just convert it to a string, and then output it.
0136         std::cout << qPrintable(cert.serialNumber().toString()) << std::endl;
0137 
0138         // The subject information shows properties of who the certificate
0139         // applies to. See the convenience routines above.
0140         dumpSubjectInfo(cert.subjectInfo());
0141 
0142         // The issuer information shows properties of who the certificate
0143         // was signed by. See the convenience routines above.
0144         dumpIssuerInfo(cert.issuerInfo());
0145 
0146         // Test if the certificate can be used as a certificate authority
0147         if (cert.isCA()) {
0148             std::cout << "Is certificate authority" << std::endl;
0149         } else {
0150             std::cout << "Is not a certificate authority" << std::endl;
0151         }
0152 
0153         // Test if the certificate is self-signed.
0154         if (cert.isSelfSigned()) {
0155             std::cout << "Self signed" << std::endl;
0156         } else {
0157             std::cout << "Is not self-signed!!!" << std::endl;
0158         }
0159 
0160         // Certificate are only valid between specific dates. We can get the dates
0161         // (as a QDateTime) using a couple of calls
0162         std::cout << "Valid from " << qPrintable(cert.notValidBefore().toString());
0163         std::cout << ", until " << qPrintable(cert.notValidAfter().toString());
0164         std::cout << std::endl;
0165 
0166         // You can get the certificate in PEM encoding with a simple toPEM() call
0167         std::cout << "PEM:" << std::endl;
0168         std::cout << qPrintable(cert.toPEM());
0169         std::cout << std::endl << std::endl;
0170     }
0171 
0172     return 0;
0173 }