changeset 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 2207e94a0cc3
children 5fa58979cb3a
files common/util.c ui/certificate.cpp ui/certificate.h
diffstat 3 files changed, 90 insertions(+), 80 deletions(-) [+]
line wrap: on
line diff
--- 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;
 }
-
--- 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 <QStringList>
 #include <QObject>
 
-#include <polarssl/x509_crt.h>
+#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"
+            "    <bold>%1</bold>\n"
+            "    %2, %3\n\n"
+            "Serial number:\n"
+            "%4\n"
+            "Valid from: <bold>%5</bold> to <bold>%6</bold>\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");
-}
--- 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 <QByteArray>
+#include <QDateTime>
 #include <QMap>
 #include <QString>
 
@@ -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 <QString, QString> mSubjectAttrs;
+    QString mSubjectOU,
+            mSubjectCN,
+            mSubjectO,
+            mSubjectSN,
+            mDetails,
+            mBaseLine;
+
+    QDateTime mValidFrom,
+              mValidTo;
 };
 #endif

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