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 }

http://wald.intevation.org/projects/trustbridge/