/* vi: set sw=4 ts=4: * * Copyright (C) 2001 - 2012 Christian Hohnstaedt. * * All rights reserved. */ #include "x509rev.h" #include "pki_base.h" #include "func.h" #include "exception.h" #include #include #include #include #define CRL_REASON_UNSPECIFIED 0 #define CRL_REASON_KEY_COMPROMISE 1 #define CRL_REASON_CA_COMPROMISE 2 #define CRL_REASON_AFFILIATION_CHANGED 3 #define CRL_REASON_SUPERSEDED 4 #define CRL_REASON_CESSATION_OF_OPERATION 5 #define CRL_REASON_CERTIFICATE_HOLD 6 #define CRL_REASON_REMOVE_FROM_CRL 8 #define CRL_REASON_PRIVILEGE_WITHDRAWN 9 #define CRL_REASON_AA_COMPROMISE 10 static ENUMERATED_NAMES crl_reasons[] = { {CRL_REASON_UNSPECIFIED, "Unspecified", "unspecified"}, {CRL_REASON_KEY_COMPROMISE, "Key Compromise", "keyCompromise"}, {CRL_REASON_CA_COMPROMISE, "CA Compromise", "CACompromise"}, {CRL_REASON_AFFILIATION_CHANGED, "Affiliation Changed", "affiliationChanged"}, {CRL_REASON_SUPERSEDED, "Superseded", "superseded"}, {CRL_REASON_CESSATION_OF_OPERATION, "Cessation Of Operation", "cessationOfOperation"}, {CRL_REASON_CERTIFICATE_HOLD, "Certificate Hold", "certificateHold"}, {CRL_REASON_REMOVE_FROM_CRL, "Remove From CRL", "removeFromCRL"}, {CRL_REASON_PRIVILEGE_WITHDRAWN, "Privilege Withdrawn", "privilegeWithdrawn"}, {CRL_REASON_AA_COMPROMISE, "AA Compromise", "AACompromise"}, {-1, NULL, NULL} }; QStringList x509rev::crlreasons() { QStringList l; for (int i=0; crl_reasons[i].lname; i++) l << crl_reasons[i].lname; return l; } QString x509rev::getReason() const { return crl_reasons[reason_idx].lname; } static int reasonBit2Idx(int bit) { for (int i=0; crl_reasons[i].lname; i++) { if (bit == crl_reasons[i].bitnum) { return i; } } return 0; } void x509rev::fromREVOKED(const X509_REVOKED *rev) { ASN1_ENUMERATED *reason; ASN1_TIME *at; int j = -1, r; if (!rev) return; serial = a1int(X509_REVOKED_get0_serialNumber(rev)); date = a1time(X509_REVOKED_get0_revocationDate(rev)); reason = (ASN1_ENUMERATED *)X509_REVOKED_get_ext_d2i( (X509_REVOKED *)rev, NID_crl_reason, &j, NULL); openssl_error(); reason_idx = 0; if (reason) { r = ASN1_ENUMERATED_get(reason); openssl_error(); reason_idx = reasonBit2Idx(r); ASN1_ENUMERATED_free(reason); } ivalDate.setUndefined(); at = (ASN1_TIME *)X509_REVOKED_get_ext_d2i((X509_REVOKED *)rev, NID_invalidity_date, &j, NULL); openssl_error(); if (at) { ivalDate = a1time(at); ASN1_GENERALIZEDTIME_free(at); } qDebug() << *this; } X509_REVOKED *x509rev::toREVOKED(bool withReason) const { a1time i = ivalDate; a1time d = date; X509_REVOKED *rev = X509_REVOKED_new(); Q_CHECK_PTR(rev); X509_REVOKED_set_serialNumber(rev, serial.get()); X509_REVOKED_set_revocationDate(rev, d.get_utc()); X509_REVOKED_add1_ext_i2d(rev, NID_invalidity_date, i.get(), 0, 0); /* RFC says to not add the extension if it is "unspecified" */ if (reason_idx != 0 && withReason) { ASN1_ENUMERATED *a = ASN1_ENUMERATED_new(); ASN1_ENUMERATED_set(a, crl_reasons[reason_idx].bitnum); X509_REVOKED_add1_ext_i2d(rev, NID_crl_reason, a, 0, 0); ASN1_ENUMERATED_free(a); } openssl_error(); qDebug() << *this; return rev; } void x509rev::d2i(QByteArray &ba) { X509_REVOKED *r; r = (X509_REVOKED *)d2i_bytearray(D2I_VOID(d2i_X509_REVOKED), ba); if (!r) return; fromREVOKED(r); X509_REVOKED_free(r); } QByteArray x509rev::i2d() const { QByteArray ba; X509_REVOKED *r = toREVOKED(); ba = i2d_bytearray(I2D_VOID(i2d_X509_REVOKED), r); X509_REVOKED_free(r); return ba; } void x509rev::set(const x509rev &x) { serial = x.serial; date = x.date; ivalDate = x.ivalDate; reason_idx = x.reason_idx; crlNo = x.crlNo; } bool x509rev::identical(const x509rev &x) const { return serial == x.serial && date == x.date && ivalDate == x.ivalDate && reason_idx == x.reason_idx; } x509rev::operator QString() const { return QString("Rev: %1 D:%2 I:%3 Reason: %4 '%5'\n") .arg(serial.toHex(), date.toSortable(), ivalDate.toSortable()) .arg(reason_idx).arg(crl_reasons[reason_idx].lname); } x509rev::x509rev(QSqlRecord rec, int offset) { serial.setHex(rec.value(offset).toString()); date.fromPlain(rec.value(offset +1).toString()); ivalDate.fromPlain(rec.value(offset +2).toString()); crlNo = rec.value(offset +3).toInt(); reason_idx = reasonBit2Idx(rec.value(offset +4).toInt()); qDebug() << *this; } void x509rev::executeQuery(XSqlQuery &q) { // 0 is the caId q.bindValue(1, serial.toHex()); q.bindValue(2, date.toPlain()); q.bindValue(3, ivalDate.toPlain()); q.bindValue(4, crlNo ? QVariant(crlNo) : QVariant()); q.bindValue(5, crl_reasons[reason_idx].bitnum); q.exec(); } void x509revList::merge(const x509revList &other) { foreach(x509rev r, other) { if (r.isValid() && !contains(r)) { merged = true; append(r); } } } bool x509revList::identical(const x509revList &other) const { if (size() != other.size()) return false; for (int i=0; i