Mercurial > trustbridge
comparison ui/certificate.cpp @ 338:64e38886f903
Use certhelp for certificate parsing and add some dummy info
author | Andre Heinecke <aheinecke@intevation.de> |
---|---|
date | Wed, 09 Apr 2014 14:26:53 +0000 |
parents | 825b42da1855 |
children | a49766196a7d b0a274f4f9e2 |
comparison
equal
deleted
inserted
replaced
337:2207e94a0cc3 | 338:64e38886f903 |
---|---|
1 #include "certificate.h" | 1 #include "certificate.h" |
2 #include <QDebug> | 2 #include <QDebug> |
3 #include <QStringList> | 3 #include <QStringList> |
4 #include <QObject> | 4 #include <QObject> |
5 | 5 |
6 #include <polarssl/x509_crt.h> | 6 #include "certhelp.h" |
7 | 7 |
8 #define POLARSSL_INFO_BUF_SIZE 2000 | 8 /* Qt wrapper around certhelp functions. */ |
9 QString getX509Value(x509_name *namebuf, unsigned char *oid) { | |
10 QString retval; | |
11 char * buf = get_oid_valstr(namebuf, oid); | |
12 if (buf == NULL) { | |
13 return retval; | |
14 } | |
15 retval = QString::fromUtf8(buf, -1); | |
16 free(buf); | |
17 return retval; | |
18 } | |
19 | |
20 void Certificate::parseDetails(const QByteArray& cert) { | |
21 x509_crt chain; | |
22 | |
23 x509_crt_init(&chain); | |
24 if (x509_crt_parse_der(&chain, (const unsigned char *)cert.data(), | |
25 cert.size()) != 0) { | |
26 qDebug() << "Failed to parse cert.."; | |
27 return; | |
28 } | |
29 | |
30 mValidFrom = QDateTime(QDate(chain.valid_from.year, | |
31 chain.valid_from.mon, | |
32 chain.valid_from.day), | |
33 QTime(chain.valid_from.hour, | |
34 chain.valid_from.min, | |
35 chain.valid_from.sec)); | |
36 | |
37 mValidTo = QDateTime(QDate(chain.valid_to.year, | |
38 chain.valid_to.mon, | |
39 chain.valid_to.day), | |
40 QTime(chain.valid_to.hour, | |
41 chain.valid_to.min, | |
42 chain.valid_to.sec)); | |
43 | |
44 mSubjectCN = getX509Value(&(chain.subject), CERT_OID_CN); | |
45 mSubjectOU = getX509Value(&(chain.subject), CERT_OID_OU); | |
46 mSubjectO = getX509Value(&(chain.subject), CERT_OID_O); | |
47 mSubjectSN = getX509Value(&(chain.subject), CERT_OID_SN); | |
48 x509_crt_free(&chain); | |
49 | |
50 mDetails = QObject::tr("Certificate:\n" | |
51 " <bold>%1</bold>\n" | |
52 " %2, %3\n\n" | |
53 "Serial number:\n" | |
54 "%4\n" | |
55 "Valid from: <bold>%5</bold> to <bold>%6</bold>\n\n" | |
56 "Issued by: ..") | |
57 .arg(mSubjectCN) | |
58 .arg(mSubjectO) | |
59 .arg(mSubjectOU) | |
60 .arg(mSubjectSN) | |
61 .arg(QLocale::system().toString(mValidFrom)) | |
62 .arg(QLocale::system().toString(mValidTo)); | |
63 } | |
9 | 64 |
10 Certificate::Certificate(const QString& b64Line) : | 65 Certificate::Certificate(const QString& b64Line) : |
11 mValid(false) | 66 mValid(false) |
12 { | 67 { |
13 int ret = -1; | |
14 char buf[POLARSSL_INFO_BUF_SIZE]; | |
15 | |
16 x509_crt x509cert; | |
17 | |
18 if (b64Line.isEmpty()) { | 68 if (b64Line.isEmpty()) { |
19 return; | 69 return; |
20 } | 70 } |
21 | 71 |
22 /* Cut of the first two chars (e.g. I: and decode) */ | 72 /* Cut of the first two chars (e.g. I: and decode) */ |
23 QByteArray asn1data = QByteArray::fromBase64( | 73 QByteArray asn1data = QByteArray::fromBase64( |
24 b64Line.right(b64Line.size() - 2).toLatin1()); | 74 b64Line.right(b64Line.size() - 2).toLatin1()); |
25 | 75 |
26 x509_crt_init(&x509cert); | 76 parseDetails(asn1data); |
27 ret = x509_crt_parse(&x509cert, | |
28 (const unsigned char*) asn1data.constData(), | |
29 asn1data.size()); | |
30 if (ret != 0) { | |
31 qDebug() << "Parsing certificate failed with error: " << ret; | |
32 qDebug() << "Failed cert: " << asn1data.toBase64(); | |
33 x509_crt_free(&x509cert); | |
34 return; | |
35 } | |
36 | 77 |
37 /* Get a full details string */ | 78 /* If the subject CN is set then at least one x509parse |
38 ret = x509_crt_info(buf, POLARSSL_INFO_BUF_SIZE, "", &x509cert); | 79 * in polarssl was successfull. And a root certificate |
39 | 80 * always needs to have a subject CN */ |
40 if (ret <= 0) { | 81 mValid = !mSubjectCN.isEmpty(); |
41 qDebug() << "Getting certificate info failed with error: " << ret; | |
42 return; | |
43 } | |
44 | |
45 /* In case of success the return value is the size of the information | |
46 * written into buf */ | |
47 mDetails = QString::fromUtf8(buf, ret); | |
48 | |
49 /* Get the subject */ | |
50 ret = x509_dn_gets(buf, POLARSSL_INFO_BUF_SIZE, &(x509cert.subject)); | |
51 | |
52 if (ret <= 0) { | |
53 qDebug() << "Getting certificate subject failed with error: " << ret; | |
54 return; | |
55 } | |
56 | |
57 /* TODO check that all asn encodings are handled */ | |
58 QString subject = QString::fromUtf8(buf, ret); | |
59 | |
60 /* TODO check that escaped , are not possible */ | |
61 QStringList attrs = subject.split(", "); | |
62 | |
63 foreach (const QString& attr, attrs) { | |
64 QStringList kv = attr.split("="); | |
65 if (kv.size() != 2) { | |
66 qDebug() << "Failed to parse subject element: " << attr; | |
67 continue; | |
68 } | |
69 mSubjectAttrs.insert(kv[0], kv[1]); | |
70 } | |
71 | |
72 /* For more information to get from a x509_crt see | |
73 * https://polarssl.org/api/x509_8h.html */ | |
74 | |
75 x509_crt_free(&x509cert); | |
76 | |
77 mValid = true; | |
78 | 82 |
79 mBaseLine = b64Line; | 83 mBaseLine = b64Line; |
80 } | 84 } |
81 | 85 |
82 QString Certificate::getSubjectAttr (const QString& attrName) const { | 86 QString Certificate::shortDescription() const { |
83 return mSubjectAttrs.value(attrName); | 87 if (!isValid()) { |
88 return QObject::tr("Failed to parse certificate"); | |
89 } | |
90 | |
91 QString ret = mSubjectCN; /* Necessary by definition */ | |
92 if (!mSubjectO.isEmpty()) { | |
93 ret += " - " + mSubjectO; | |
94 } | |
95 if (!mSubjectOU.isEmpty()) { | |
96 ret += ", " + mSubjectOU; | |
97 } | |
98 return ret; | |
84 } | 99 } |
85 | |
86 QString Certificate::shortDescription() const { | |
87 return getSubjectAttr("CN"); | |
88 } |