1 | /* |
2 | Copyright (C) 2003 Justin Karneges <justin@affinix.com> |
3 | Copyright (C) 2005 Brad Hards <bradh@frogmouth.net> |
4 | |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy |
6 | of this software and associated documentation files (the "Software"), to deal |
7 | in the Software without restriction, including without limitation the rights |
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
9 | copies of the Software, and to permit persons to whom the Software is |
10 | furnished to do so, subject to the following conditions: |
11 | |
12 | The above copyright notice and this permission notice shall be included in |
13 | all copies or substantial portions of the Software. |
14 | |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
18 | AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN |
19 | AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
21 | */ |
22 | |
23 | #include <QtCrypto> |
24 | |
25 | #include <QCoreApplication> |
26 | #include <QFile> |
27 | |
28 | #include <iostream> |
29 | |
30 | #ifdef QT_STATICPLUGIN |
31 | #include "import_plugins.h" |
32 | #endif |
33 | |
34 | // dump out information about some part of the certificate |
35 | // we use this same approach for information about the subject |
36 | // of the certificate, and also about the issuer of the certificate |
37 | static void dumpCertificateInfo(const QCA::CertificateInfo &info) |
38 | { |
39 | std::cout << " Organization: " << std::endl; |
40 | |
41 | // Note that a single certificate can apply to more than one |
42 | // organisation. QCA::Certificate is a multimap, so when you |
43 | // ask for the values associated with a parameter, it returns |
44 | // a list. |
45 | QList<QString> orgInfoList = info.values(key: QCA::Organization); |
46 | |
47 | // foreach() interates over each value in the list, and we dump |
48 | // out each value. Note that is uncommon for a certificate to |
49 | // actually contain multiple values for a single parameter. |
50 | QString organization; |
51 | foreach (organization, orgInfoList) { |
52 | std::cout << " " << qPrintable(organization) << std::endl; |
53 | } |
54 | |
55 | std::cout << " Country: " << std::endl; |
56 | // As above, however this shows a more compact way to represent |
57 | // the iteration and output. |
58 | foreach (QString country, info.values(QCA::Country)) { // clazy:exclude=container-anti-pattern |
59 | std::cout << " " << qPrintable(country) << std::endl; |
60 | } |
61 | } |
62 | |
63 | // This is just a convenience routine |
64 | static void dumpSubjectInfo(const QCA::CertificateInfo &subject) |
65 | { |
66 | std::cout << "Subject: " << std::endl; |
67 | |
68 | dumpCertificateInfo(info: subject); |
69 | } |
70 | |
71 | // This is just a convenience routine |
72 | static void dumpIssuerInfo(const QCA::CertificateInfo &issuer) |
73 | { |
74 | std::cout << "Issuer: " << std::endl; |
75 | |
76 | dumpCertificateInfo(info: issuer); |
77 | } |
78 | |
79 | int main(int argc, char **argv) |
80 | { |
81 | // the Initializer object sets things up, and |
82 | // also does cleanup when it goes out of scope |
83 | QCA::Initializer init; |
84 | |
85 | QCoreApplication app(argc, argv); |
86 | |
87 | // We need to ensure that we have certificate handling support |
88 | if (!QCA::isSupported(features: "cert" )) { |
89 | std::cout << "Sorry, no PKI certificate support" << std::endl; |
90 | return 1; |
91 | } |
92 | |
93 | // We are going to work with a number of certificates, and a |
94 | // QList is a great template class for that |
95 | QList<QCA::Certificate> certlist; |
96 | |
97 | // We do two different cases - if we provide an argument, it is taken |
98 | // as a filename to read the keys from. If there is no argument, we just |
99 | // read from the system store certificates. |
100 | if (argc >= 2) { |
101 | // we are going to read the certificates in using a single call |
102 | // which requires a CertificateCollection. |
103 | QCA::CertificateCollection filecerts; |
104 | // The conversion can be tested (although you don't have to) to find out if it |
105 | // worked. |
106 | QCA::ConvertResult importResult; |
107 | // This imports all the PEM encoded certificates from the file specified as the argument |
108 | // Note that you pass in a pointer to the result argument. |
109 | filecerts = QCA::CertificateCollection::fromFlatTextFile(fileName: QFile::decodeName(localFileName: argv[1]), result: &importResult); |
110 | if (QCA::ConvertGood == importResult) { |
111 | std::cout << "Import succeeded" << std::endl; |
112 | // this turns the CertificateCollection into a QList of Certificate objects |
113 | certlist = filecerts.certificates(); |
114 | } |
115 | } else { |
116 | // we have no arguments, so just use the system certificates |
117 | if (!QCA::haveSystemStore()) { |
118 | std::cout << "System certificates not available" << std::endl; |
119 | return 2; |
120 | } |
121 | |
122 | // Similar to above, except we just want the system certificates |
123 | QCA::CertificateCollection systemcerts = QCA::systemStore(); |
124 | |
125 | // this turns the CertificateCollection into a QList of Certificate objects |
126 | certlist = systemcerts.certificates(); |
127 | } |
128 | |
129 | std::cout << "Number of certificates: " << certlist.count() << std::endl; |
130 | |
131 | QCA::Certificate cert; |
132 | foreach (cert, certlist) { |
133 | std::cout << "Serial Number:" ; |
134 | // the serial number of the certificate is a QCA::BigInteger, but we can |
135 | // just convert it to a string, and then output it. |
136 | std::cout << qPrintable(cert.serialNumber().toString()) << std::endl; |
137 | |
138 | // The subject information shows properties of who the certificate |
139 | // applies to. See the convenience routines above. |
140 | dumpSubjectInfo(subject: cert.subjectInfo()); |
141 | |
142 | // The issuer information shows properties of who the certificate |
143 | // was signed by. See the convenience routines above. |
144 | dumpIssuerInfo(issuer: cert.issuerInfo()); |
145 | |
146 | // Test if the certificate can be used as a certificate authority |
147 | if (cert.isCA()) { |
148 | std::cout << "Is certificate authority" << std::endl; |
149 | } else { |
150 | std::cout << "Is not a certificate authority" << std::endl; |
151 | } |
152 | |
153 | // Test if the certificate is self-signed. |
154 | if (cert.isSelfSigned()) { |
155 | std::cout << "Self signed" << std::endl; |
156 | } else { |
157 | std::cout << "Is not self-signed!!!" << std::endl; |
158 | } |
159 | |
160 | // Certificate are only valid between specific dates. We can get the dates |
161 | // (as a QDateTime) using a couple of calls |
162 | std::cout << "Valid from " << qPrintable(cert.notValidBefore().toString()); |
163 | std::cout << ", until " << qPrintable(cert.notValidAfter().toString()); |
164 | std::cout << std::endl; |
165 | |
166 | // You can get the certificate in PEM encoding with a simple toPEM() call |
167 | std::cout << "PEM:" << std::endl; |
168 | std::cout << qPrintable(cert.toPEM()); |
169 | std::cout << std::endl << std::endl; |
170 | } |
171 | |
172 | return 0; |
173 | } |
174 | |