# HG changeset patch # User Andre Heinecke # Date 1397053613 0 # Node ID 64e38886f90336be2a9706022530f3aaf8f3dbac # Parent 2207e94a0cc3ff5672f31979528ffe01f68c7abd Use certhelp for certificate parsing and add some dummy info diff -r 2207e94a0cc3 -r 64e38886f903 common/util.c --- a/common/util.c Wed Apr 09 14:25:54 2014 +0000 +++ b/common/util.c Wed Apr 09 14:26:53 2014 +0000 @@ -29,4 +29,3 @@ #endif return ret; } - diff -r 2207e94a0cc3 -r 64e38886f903 ui/certificate.cpp --- a/ui/certificate.cpp Wed Apr 09 14:25:54 2014 +0000 +++ b/ui/certificate.cpp Wed Apr 09 14:26:53 2014 +0000 @@ -3,18 +3,68 @@ #include #include -#include +#include "certhelp.h" -#define POLARSSL_INFO_BUF_SIZE 2000 +/* Qt wrapper around certhelp functions. */ +QString getX509Value(x509_name *namebuf, unsigned char *oid) { + QString retval; + char * buf = get_oid_valstr(namebuf, oid); + if (buf == NULL) { + return retval; + } + retval = QString::fromUtf8(buf, -1); + free(buf); + return retval; +} + +void Certificate::parseDetails(const QByteArray& cert) { + x509_crt chain; + + x509_crt_init(&chain); + if (x509_crt_parse_der(&chain, (const unsigned char *)cert.data(), + cert.size()) != 0) { + qDebug() << "Failed to parse cert.."; + return; + } + + mValidFrom = QDateTime(QDate(chain.valid_from.year, + chain.valid_from.mon, + chain.valid_from.day), + QTime(chain.valid_from.hour, + chain.valid_from.min, + chain.valid_from.sec)); + + mValidTo = QDateTime(QDate(chain.valid_to.year, + chain.valid_to.mon, + chain.valid_to.day), + QTime(chain.valid_to.hour, + chain.valid_to.min, + chain.valid_to.sec)); + + mSubjectCN = getX509Value(&(chain.subject), CERT_OID_CN); + mSubjectOU = getX509Value(&(chain.subject), CERT_OID_OU); + mSubjectO = getX509Value(&(chain.subject), CERT_OID_O); + mSubjectSN = getX509Value(&(chain.subject), CERT_OID_SN); + x509_crt_free(&chain); + + mDetails = QObject::tr("Certificate:\n" + " %1\n" + " %2, %3\n\n" + "Serial number:\n" + "%4\n" + "Valid from: %5 to %6\n\n" + "Issued by: ..") + .arg(mSubjectCN) + .arg(mSubjectO) + .arg(mSubjectOU) + .arg(mSubjectSN) + .arg(QLocale::system().toString(mValidFrom)) + .arg(QLocale::system().toString(mValidTo)); +} Certificate::Certificate(const QString& b64Line) : mValid(false) { - int ret = -1; - char buf[POLARSSL_INFO_BUF_SIZE]; - - x509_crt x509cert; - if (b64Line.isEmpty()) { return; } @@ -23,66 +73,27 @@ QByteArray asn1data = QByteArray::fromBase64( b64Line.right(b64Line.size() - 2).toLatin1()); - x509_crt_init(&x509cert); - ret = x509_crt_parse(&x509cert, - (const unsigned char*) asn1data.constData(), - asn1data.size()); - if (ret != 0) { - qDebug() << "Parsing certificate failed with error: " << ret; - qDebug() << "Failed cert: " << asn1data.toBase64(); - x509_crt_free(&x509cert); - return; - } - - /* Get a full details string */ - ret = x509_crt_info(buf, POLARSSL_INFO_BUF_SIZE, "", &x509cert); - - if (ret <= 0) { - qDebug() << "Getting certificate info failed with error: " << ret; - return; - } - - /* In case of success the return value is the size of the information - * written into buf */ - mDetails = QString::fromUtf8(buf, ret); - - /* Get the subject */ - ret = x509_dn_gets(buf, POLARSSL_INFO_BUF_SIZE, &(x509cert.subject)); + parseDetails(asn1data); - if (ret <= 0) { - qDebug() << "Getting certificate subject failed with error: " << ret; - return; - } - - /* TODO check that all asn encodings are handled */ - QString subject = QString::fromUtf8(buf, ret); - - /* TODO check that escaped , are not possible */ - QStringList attrs = subject.split(", "); - - foreach (const QString& attr, attrs) { - QStringList kv = attr.split("="); - if (kv.size() != 2) { - qDebug() << "Failed to parse subject element: " << attr; - continue; - } - mSubjectAttrs.insert(kv[0], kv[1]); - } - - /* For more information to get from a x509_crt see - * https://polarssl.org/api/x509_8h.html */ - - x509_crt_free(&x509cert); - - mValid = true; + /* If the subject CN is set then at least one x509parse + * in polarssl was successfull. And a root certificate + * always needs to have a subject CN */ + mValid = !mSubjectCN.isEmpty(); mBaseLine = b64Line; } -QString Certificate::getSubjectAttr (const QString& attrName) const { - return mSubjectAttrs.value(attrName); +QString Certificate::shortDescription() const { + if (!isValid()) { + return QObject::tr("Failed to parse certificate"); + } + + QString ret = mSubjectCN; /* Necessary by definition */ + if (!mSubjectO.isEmpty()) { + ret += " - " + mSubjectO; + } + if (!mSubjectOU.isEmpty()) { + ret += ", " + mSubjectOU; + } + return ret; } - -QString Certificate::shortDescription() const { - return getSubjectAttr("CN"); -} diff -r 2207e94a0cc3 -r 64e38886f903 ui/certificate.h --- a/ui/certificate.h Wed Apr 09 14:25:54 2014 +0000 +++ b/ui/certificate.h Wed Apr 09 14:26:53 2014 +0000 @@ -7,6 +7,7 @@ */ #include +#include #include #include @@ -48,7 +49,8 @@ /** @brief get details for the certificate * - * Get the X509 information that is returned by x509_crt_info + * Get a formatted details string usable for user visible + * certificate details. * **/ const QString& details() const {return mDetails;} @@ -62,17 +64,6 @@ **/ const QString& base64Line() const {return mBaseLine;} - /** @brief get a single attribute of the subject - * - * Returns a single attribute of the subject such as the - * common name. - * - * @param[in] attr the Attribute name. to get e.g. "CN" - * - * @returns the value of the attribute or a null string - **/ - QString getSubjectAttr(const QString& attr) const; - /** @brief Check if this certificate has the install instruction. * * This is shorthand for baseLine.startsWith("I:"); @@ -80,11 +71,20 @@ bool isInstallCert() const {return mBaseLine.startsWith("I:");} private: + /** @brief Helper function to parse the details of a certificate **/ + void parseDetails(const QByteArray& cert); + bool mValid; bool mInstCert; - QString mDetails; - QString mBaseLine; - QMap mSubjectAttrs; + QString mSubjectOU, + mSubjectCN, + mSubjectO, + mSubjectSN, + mDetails, + mBaseLine; + + QDateTime mValidFrom, + mValidTo; }; #endif